#include "mungal4.h"
#pragma hdrstop

#define PRELOAD_ART

#include "..\munga\player.h"
#include "l4app.h"
#include "l4gauge.h"
#include "l4grend.h"

// #define LOCAL_TEST

#if defined(LOCAL_TEST)
#	define Test_Tell(n) std::cout << n
#else
#	define Test_Tell(n)
#endif


LookupTable
	configureChannels[] =
		{
			{"red",   L4GraphicsPort::RedChannel},
			{"green", L4GraphicsPort::GreenChannel},
			{"blue",  L4GraphicsPort::BlueChannel},
			{"rgb",   L4GraphicsPort::AllChannels},

			{"direct", L4GraphicsPort::DirectColor},
			{"blank", L4GraphicsPort::BlankColor},

			{"redtransparent",   L4GraphicsPort::RedChannelTransparentZero},
			{"greentransparent", L4GraphicsPort::GreenChannelTransparentZero},
			{"bluetransparent",  L4GraphicsPort::BlueChannelTransparentZero},
			{"rgbtransparent",   L4GraphicsPort::AllChannelsTransparentZero},
			{NULL, -1} 
		};

LookupTable
	configurePalettes[] =
		{
			{"native", SVGA16::NativePalette},
			{"clut0",  SVGA16::SecondaryPalette},
			{"clut1",  SVGA16::AuxiliaryPalette1},
			{"clut2",  SVGA16::AuxiliaryPalette2},
			{NULL, -1} 
		};

LookupTable
	configureFormat[] =
		{
			{"unsigned",           NumericDisplay::unsignedFormat},
			{"signed",             NumericDisplay::signedFormat},
			{"signedBlankedZeros", NumericDisplay::signedBlankedZerosFormat},
			{"absolute",           NumericDisplay::absoluteFormat},
			{"time",               NumericDisplay::timeFormat},
			{NULL, -1} 
		};

LookupTable
	configureDirection[] =
		{
			{"left",  WipeGaugeScalar::wipeLeft},
			{"down",  WipeGaugeScalar::wipeDown},
			{"right", WipeGaugeScalar::wipeRight},
			{"up",    WipeGaugeScalar::wipeUp},
			{NULL, -1} 
		};

char
	*nameCopy(const char *old_name)
{
	Check_Pointer(old_name);

	char
		*copy = strdup(old_name);
	Register_Pointer(copy);

	return copy;
}

//###########################################################################
// NumericDisplay
//###########################################################################
NumericDisplay::NumericDisplay(
	L4Warehouse *the_warehouse,
	int x_position, int y_position,
	const char *font_name,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color
)
{
	Check_Pointer(this);

	//------------------------------------------------------------
	// Save the font name
	//------------------------------------------------------------
	digitMapName = nameCopy(font_name);
	//------------------------------------------------------------
	// Order the font from the warehouse (pre-load for future use)
	//------------------------------------------------------------
	Check(the_warehouse);
	warehouse = the_warehouse;

	Check_Pointer(digitMapName);

	BitMap
		*digit_map = warehouse->bitMapBin.Get(digitMapName);
	//-----------------------------------------------------------
	// Calculate font-specific values
	//-----------------------------------------------------------
	if (digit_map == NULL)
	{
		digitWidth  = 0;
		digitHeight = 0;
	}
	else
	{
		Check(digit_map);
		digitWidth  = (digit_map->Data.Size.x+1)/totalDigitsPerFont;
		digitHeight = digit_map->Data.Size.y;
	}
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	if (number_of_digits < 1)
	{
		number_of_digits = 1;
	}

	if (format == timeFormat)
	{
		if (number_of_digits > 8)
		{
			number_of_digits = 8;
		}
		largestValue = (Scalar) (99*60*60);
	}
	else
	{
		if (number_of_digits > maxDigits)
		{
			number_of_digits = maxDigits;
		}
		largestValue = (Scalar) (pow(10.0f, number_of_digits)-1.0);
	}

	numberOfDigits  = number_of_digits;
	format          = requested_format;
	backgroundColor = background_color;
	foregroundColor = foreground_color;
	offsetX = x_position;
	offsetY = y_position;
	erased = True;

	ForceUpdate();			// ensure initialization

	//------------------------------------------------------------
	// Done with the font, release it
	//------------------------------------------------------------
#	if !defined(PRELOAD_ART)
		Check_Pointer(warehouse);
		warehouse->bitMapBin.Release(digitMapName);
#	endif

	Check_Fpu();
}

NumericDisplay::~NumericDisplay()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		warehouse->bitMapBin.Release(digitMapName);
#	endif
	//------------------------------------------------------------
	// Delete the font name
	//------------------------------------------------------------
	Unregister_Pointer(digitMapName);
	delete[] digitMapName;
	digitMapName = NULL;

	Check_Fpu();
}

Logical
	NumericDisplay::TestInstance() const
{
	return True;
}

void
	NumericDisplay::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "NumericDisplay:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
	std::cout << temp << "foregroundColor=" << foregroundColor << "\n";
	std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n";
	std::cout << temp << "format         =";
	switch(format)
	{
	case unsignedFormat:           std::cout << "unsignedFormat\n"; break;
	case signedFormat:             std::cout << "signedFormat\n"; break;
	case signedBlankedZerosFormat: std::cout << "signedBlankedZerosFormat\n"; break;
	case absoluteFormat:           std::cout << "absoluteFormat\n"; break;
	case timeFormat:               std::cout << "timeFormat\n"; break;
	default: 
		std::cout << "**OUT OF RANGE**\n";
	}

	Check_Fpu();
}

void
	NumericDisplay::ForceUpdate()
{
	Check(this);
	//-----------------------------------------------------------
	// Force update by clearing previous value and digits
	//-----------------------------------------------------------
	previousValue = -1.2345f;

	for(int i=0; i<maxDigits; ++i)
	{
		previousDigit[i] = -1;
	}
	Check_Fpu();
}

void
	NumericDisplay::SetColors(int bg_color, int fg_color)
{
	Check(this);
	backgroundColor = bg_color;
	foregroundColor = fg_color;
	ForceUpdate();
	Check_Fpu();
}

void
	NumericDisplay::Draw(
		GraphicsView *graphics_view,
		Scalar current_value
	)
{
	Check(this);

	if (erased)
	{
		erased = False;
		ForceUpdate();
	}
	//-----------------------------------------------------------
	// Get and lock the font so that we may use it
	//-----------------------------------------------------------
	Check(warehouse);

	BitMap
		*digit_map = warehouse->bitMapBin.Get(digitMapName);

	if (digit_map != NULL)
	{
		//
		//-----------------------------------------------------------
		// Get absolute value if required
		//-----------------------------------------------------------
		//
		if(format == absoluteFormat)
		{
			if (current_value < 0.0)
			{
				current_value = - current_value;
			}
		}
		Check_Fpu();

		//
		//-----------------------------------------------------------
		// Draw only if value has changed
		//-----------------------------------------------------------
		//
		if (previousValue != current_value)
		{
			previousValue = current_value;

			int
				test_value((int) (current_value+.5)),
				digit_height(digit_map->Data.Size.y),
				i,
				x,
				sx;
			Check_Fpu();

			char
				buffer[maxDigits+1],
				*buffer_pointer;

			//
			//--------------------------------------------------------
			// Get absolute value, limit to maximum
			//--------------------------------------------------------
			//
			if (test_value < 0)
			{
				test_value = - test_value;
			}

			if (test_value > (int) largestValue)
			{
				test_value = (int) largestValue;
			}
			Check_Fpu();

			//
			//--------------------------------------------------------
			// Build buffer
			//--------------------------------------------------------
			//
			buffer_pointer = &buffer[numberOfDigits-1];

			switch (format)
			{
			case absoluteFormat:
			case unsignedFormat:
			case signedBlankedZerosFormat:
				for(i=numberOfDigits-1; i>=0; --i)
				{
					*buffer_pointer-- = (char) (test_value % 10);
					test_value /= 10;
				}
				Check_Fpu();
				break;

			case signedFormat:
				for(i=numberOfDigits-2; i>=0; --i)
				{
					*buffer_pointer-- = (char) (test_value % 10);
					test_value /= 10;
				}
				*buffer_pointer = (char)
					((current_value >= 0.0) ? plusDigit : minusDigit);
				Check_Fpu();
				break;

			case timeFormat:
				{
					int
						n,
						state;

					state = 0;
					for(i=numberOfDigits; i>0; )
					{
						switch(state++)
						{
						case 0:	// seconds
						case 1:	// minutes
							n = test_value % 60;
							test_value /= 60;
							break;

						case 2:	// hours
							n = test_value % 24;
							test_value /= 24;
							break;

						case 3:	// days
							n = test_value % 100;
							break;

						default:	// Oh, come on now!
							n = 0;
							break;
						}
						Check_Fpu();
						if (--i >= 0)
						{
							*buffer_pointer-- = (char) (n % 10);
						}
						if (--i >= 0)
						{
							*buffer_pointer-- = (char) (n / 10);
						}
						if (--i >= 0)
						{
							*buffer_pointer-- = (char) colonDigit;
						}
					}
				}
				break;
			}
			Check_Fpu();

			//
			//--------------------------------------------------------
			// Draw digits from buffer
			//--------------------------------------------------------
			//
			Logical
				blanked = True;

			char
				this_digit;

			for(
					i=0, x=offsetX, buffer_pointer=buffer;
					i<numberOfDigits;
					++i, x+=digitWidth, ++buffer_pointer
				)
			{
				//-----------------------------------------------------
				// Get 'new' digit
				//-----------------------------------------------------
				this_digit = *buffer_pointer;

				//-----------------------------------------------------
				// Special processing for blanked leading zeros
				//-----------------------------------------------------
				if (format == signedBlankedZerosFormat)
				{
					if (blanked)
					{
						//-----------------------------------------------------
						// If negative, and next digit non-zero, draw (-)
						//-----------------------------------------------------
						if ((current_value < 0.0) && (*(buffer_pointer+1) != 0))
						{
							this_digit= minusDigit;
							blanked = False;
						}
						//-----------------------------------------------------
						// Else if non-zero, turn off blanking
						//-----------------------------------------------------
						else if (this_digit != 0)
						{
							blanked = False;
						}
						//-----------------------------------------------------
						// Else if last character, turn off blanking
						//-----------------------------------------------------
						else if (i==(numberOfDigits-1))
						{
							blanked = False;
						}
						//-----------------------------------------------------
						// Else blank the leading zero
						//-----------------------------------------------------
						else
						{
							this_digit = blankedDigit;
						}
					}
				}
				Check_Fpu();

				//-----------------------------------------------------
				// Draw only changed digits
				//-----------------------------------------------------
				if (previousDigit[i] != this_digit)
				{
					previousDigit[i] = this_digit;

					//-----------------------------------------------------
					// Move to digit location
					//-----------------------------------------------------
					graphics_view->MoveToAbsolute(x, offsetY);
					//-----------------------------------------------------
					// If blanked, draw filled rectangle
					//-----------------------------------------------------
					if (this_digit == blankedDigit)
					{
						graphics_view->SetColor(backgroundColor);
						graphics_view->DrawFilledRectangleToRelative(
							digitWidth,
							digit_height
						);
					}
					//-----------------------------------------------------
					// Else draw character
					//-----------------------------------------------------
					else
					{
						sx = digitWidth*this_digit;

						graphics_view->SetColor(foregroundColor);
						graphics_view->DrawBitMapOpaque(
							backgroundColor,
							0,	//rotation
							digit_map,
							sx, 0, sx+digitWidth-1, digit_height
						);
					}
				}
			}
		}
	}
	//-----------------------------------------------------------
	// Unlock the font: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->bitMapBin.Release(digitMapName);

	Check_Fpu();
}

void
	NumericDisplay::Erase(
		GraphicsView *graphics_view
	)
{
	Check(this);

	if (!erased)
	{
		erased = True;

		graphics_view->SetColor(backgroundColor);
		graphics_view->MoveToAbsolute(offsetX, offsetY);
		graphics_view->DrawFilledRectangleToRelative(
			digitWidth*numberOfDigits,
			digitHeight
		);
	}
	Check_Fpu();
}


//###########################################################################
// NumericDisplayScalar
//###########################################################################
MethodDescription
	NumericDisplayScalar::methodDescription =
		{
			"numeric",
			NumericDisplayScalar::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeInteger, NULL },		// # of digits
				{ ParameterDescription::typeString, NULL },		// format
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	NumericDisplayScalar::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeString);		// font name
	parameterList[4].CheckIt(ParameterDescription::typeInteger);	// # of digs
	parameterList[5].CheckIt(ParameterDescription::typeString);		// format
	parameterList[6].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[7].CheckIt(ParameterDescription::typeColor);		// foreground
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);	// value name
#	endif

	Test_Tell("NumericDisplayScalar::Make\n");
	Check(gauge_renderer);

	int
		number_format = configureFormat[0].Search(
			parameterList[5].data.string
		);

	if (number_format < 0)
	{
		Test_Tell("NumericDisplayScalar::Make format NOT FOUND\n");
		Check_Fpu();
		return False;
	}

#	if DEBUG_LEVEL > 0
	NumericDisplayScalar
		*numeric_display =
#	endif
			new NumericDisplayScalar(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,		//font name
				parameterList[4].data.integer,	//int number_of_chars
				(NumericDisplay::NumericFormat) number_format,
				parameterList[6].data.integer,	//int background_color
				parameterList[7].data.integer,	//int foreground_color
				(Scalar *) parameterList[8].data.attributePointer

				// HACK!!!! The (Scalar *) is VERY dangerous!
			);
	Register_Object(numeric_display);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("NumericDisplayScalar::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("NumericDisplayScalar::Make OK\n");
	Check_Fpu();
	return True;
}

NumericDisplayScalar::NumericDisplayScalar(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *font_name,		//BitMap *font,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color,
	Scalar *value_pointer,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	// graphics_port may be NULL!
	Check_Pointer(value_pointer);
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	numericDisplay = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		0,0,
		font_name,
		number_of_digits,
		requested_format,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplay);

	localView.SetPositionWithinPort(left, bottom, right, top);

	//
	//-----------------------------------------------------------
	// Build connection to value
	//-----------------------------------------------------------
	//
	GaugeConnection
		*connection;

	connection = new
		GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
	Register_Object(connection);
	AddConnection(connection);
	Check_Fpu();
}

NumericDisplayScalar::~NumericDisplayScalar()
{
	Check(this);

	//-------------------------------------------------
	// Destroy the numeric display
	//-------------------------------------------------
	if (numericDisplay != NULL)
	{
		Unregister_Object(numericDisplay);
		delete numericDisplay;
		numericDisplay = NULL;
	}

	// base class deletes all connections in Gauge::~Gauge
	Check_Fpu();
}

Logical
	NumericDisplayScalar::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	NumericDisplayScalar::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "NumericDisplayScalar:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	GraphicGauge::ShowInstance(temp);
	Check(numericDisplay);
	numericDisplay->ShowInstance(temp);
	Check_Fpu();
}

void
	NumericDisplayScalar::BecameActive()
{
	Check(this);
	Check(numericDisplay);
	numericDisplay->ForceUpdate();
	Check_Fpu();
}

void
	NumericDisplayScalar::SetColors(int bg_color, int fg_color)
{
	Check(this);
	numericDisplay->SetColors(bg_color, fg_color);
	Check_Fpu();
}

void
	NumericDisplayScalar::Execute()
{
	Check(this);
	Check(numericDisplay);
	numericDisplay->Draw(&localView, currentValue);
	Check_Fpu();
}

//###########################################################################
// NumericDisplaySpeed
//
// - Converts input in meters per second to display as kilometers per hour
//###########################################################################
MethodDescription
	NumericDisplaySpeed::methodDescription =
		{
			"numericSpeed",
			NumericDisplaySpeed::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeInteger, NULL },		// # of digits
				{ ParameterDescription::typeString, NULL },		// format
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	NumericDisplaySpeed::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeString);		// font name
	parameterList[4].CheckIt(ParameterDescription::typeInteger);	// # of digs
	parameterList[5].CheckIt(ParameterDescription::typeString);		// format
	parameterList[6].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[7].CheckIt(ParameterDescription::typeColor);		// foreground
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);	// value name
#	endif

	Test_Tell("NumericDisplaySpeed::Make\n");

	int
		number_format = configureFormat[0].Search(
			parameterList[5].data.string
		);

	if (number_format < 0)
	{
		Test_Tell("NumericDisplaySpeed::Make format NOT FOUND\n");
		Check_Fpu();
		return False;
	} 

#	if DEBUG_LEVEL > 0
	NumericDisplaySpeed
		*numeric_display =
#	endif
			new NumericDisplaySpeed(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,		//font name
				parameterList[4].data.integer,	//int number_of_chars
				(NumericDisplay::NumericFormat) number_format,
				parameterList[6].data.integer,	//int background_color
				parameterList[7].data.integer,	//int foreground_color
				(Scalar *) parameterList[8].data.attributePointer

				// HACK!!!! The (Scalar *) is VERY dangerous!
			);

	Register_Object(numeric_display);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("NumericDisplaySpeed::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("NumericDisplaySpeed::Make OK\n");
	Check_Fpu();
	return True;
}

NumericDisplaySpeed::NumericDisplaySpeed(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *font_name,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color,
	Scalar *value_pointer
):
	NumericDisplayScalar(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		left, bottom, right, top,
		font_name,
		number_of_digits,
		requested_format,
		background_color, foreground_color,
		value_pointer
	)
{
	Check_Fpu();
}

void
	NumericDisplaySpeed::Execute()
{
	Check(this);

	Scalar
		value = currentValue*(Scalar)3.6;

	Check(numericDisplay);
	numericDisplay->Draw(&localView, fabs(value));
	Check_Fpu();
}

//###########################################################################
// NumericDisplayInteger
//###########################################################################
MethodDescription
	NumericDisplayInteger::methodDescription =
		{
			"numericInteger",
			NumericDisplayInteger::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeInteger, NULL },		// # of digits
				{ ParameterDescription::typeString, NULL },		// format
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	NumericDisplayInteger::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeString);		// font
	parameterList[4].CheckIt(ParameterDescription::typeInteger);	// # of digs
	parameterList[5].CheckIt(ParameterDescription::typeString);		// format
	parameterList[6].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[7].CheckIt(ParameterDescription::typeColor);		// foreground
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);	// value name
#	endif

	Test_Tell("NumericDisplayInteger::Make\n");

	int
		number_format = configureFormat[0].Search(
			parameterList[5].data.string
		);

	if (number_format < 0)
	{
		Test_Tell("NumericDisplayInteger::Make format NOT FOUND\n");
		Check_Fpu();
		return False;
	}

#	if DEBUG_LEVEL > 0
	NumericDisplayInteger
		*numeric_display =
#	endif
			new NumericDisplayInteger(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x,
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,		//font name
				parameterList[4].data.integer,	//int number_of_chars
				(NumericDisplay::NumericFormat) number_format,
				parameterList[6].data.integer,	//int background_color
				parameterList[7].data.integer,	//int foreground_color
				(int *) parameterList[8].data.attributePointer

				// HACK!!!! The (int *) is VERY dangerous!
			);
	Register_Object(numeric_display);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("NumericDisplayInteger::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("NumericDisplayInteger::Make OK\n");
	Check_Fpu();
	return True;
}

NumericDisplayInteger::NumericDisplayInteger(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *font_name,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color,
	int *value_pointer,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	// graphics_port may be NULL!
	Check_Pointer(value_pointer);
	Check(renderer);
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	numericDisplay = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		0,0,
		font_name,
		number_of_digits,
		requested_format,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplay);

	localView.SetPositionWithinPort(left, bottom, right, top);
	//-----------------------------------------------------------
	// Build connection to value
	//-----------------------------------------------------------
	GaugeConnection
		*connection;

	connection = new
		GaugeConnectionDirectOf<int>(0, &currentValue, value_pointer);
	Register_Object(connection);
	AddConnection(connection);
	Check_Fpu();
}

NumericDisplayInteger::~NumericDisplayInteger()
{
	Check(this);

	if (numericDisplay != NULL)
	{
		Unregister_Object(numericDisplay);
		delete numericDisplay;
		numericDisplay = NULL;
	}

	// base class deletes all connections in Gauge::~Gauge
	Check_Fpu();
}

Logical
	NumericDisplayInteger::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	NumericDisplayInteger::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "NumericDisplayInteger:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	GraphicGauge::ShowInstance(temp);
	Check(numericDisplay);
	numericDisplay->ShowInstance(temp);
	Check_Fpu();
}

void
	NumericDisplayInteger::BecameActive()
{
	Check(this);
	Check(numericDisplay);
	numericDisplay->ForceUpdate();
	Check_Fpu();
}

void
	NumericDisplayInteger::SetColors(int bg_color, int fg_color)
{
	Check(this);
	numericDisplay->SetColors(bg_color, fg_color);
	Check_Fpu();
}

void
	NumericDisplayInteger::Execute()
{
	Check(this);
	Check(numericDisplay);
	numericDisplay->Draw(&localView, (Scalar) currentValue);
	Check_Fpu();
}

//###########################################################################
// DigitalClock
//###########################################################################
MethodDescription
	DigitalClock::methodDescription =
		{
			"digitalClock",
			DigitalClock::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeInteger, NULL },		// # of digits
				{ ParameterDescription::typeString, NULL },		// format
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				//{ ParameterDescription::typeEmpty, NULL },
				{ ParameterDescription::typeEmpty, NULL }
			}
		};

Logical
	DigitalClock::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeString);		// font name
	parameterList[4].CheckIt(ParameterDescription::typeInteger);	// # of digs
	parameterList[5].CheckIt(ParameterDescription::typeString);		// format
	parameterList[6].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[7].CheckIt(ParameterDescription::typeColor);		// foreground
#	endif

	Test_Tell("DigitalClock::Make\n");

	int
		number_format = configureFormat[0].Search(
			parameterList[5].data.string
		);

	if (number_format < 0)
	{
		Test_Tell("DigitalClock::Make format NOT FOUND\n");
		Check_Fpu();
		return False;
	} 

#	if DEBUG_LEVEL > 0
	DigitalClock
		*digital_clock =
#	endif
			new DigitalClock(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,		//font name
				parameterList[4].data.integer,	//int number_of_chars
				(NumericDisplay::NumericFormat) number_format,
				parameterList[6].data.integer,	//int background_color
				parameterList[7].data.integer		//int foreground_color
			);

	Register_Object(digital_clock);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("DigitalClock::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("DigitalClock::Make OK\n");
	Check_Fpu();
	return True;
}

DigitalClock::DigitalClock(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *font_name,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	// graphics_port may be NULL!
	Check(renderer);

	Verify((right - left - 1) >= 0);
	Verify((top - bottom - 1) >= 0);
	//
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	//
	numericDisplay = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		0,0,
		font_name,
		number_of_digits,
		requested_format,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplay);

	localView.SetPositionWithinPort(left, bottom, right, top);

	Check_Fpu();
}

DigitalClock::~DigitalClock()
{
	Check(this);

	if (numericDisplay != NULL)
	{
		Unregister_Object(numericDisplay);
		delete numericDisplay;
		numericDisplay = NULL;
	}
	Check_Fpu();
}

Logical
	DigitalClock::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	DigitalClock::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "DigitalClock:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "numericDisplay=" << numericDisplay << "\n";
	Gauge::ShowInstance(temp);
	Check(numericDisplay);
	numericDisplay->ShowInstance(temp);
	Check_Fpu();
}

void
	DigitalClock::BecameActive()
{
	Check(this);
	Check(numericDisplay);
	numericDisplay->ForceUpdate();
	Check_Fpu();
}

void
	DigitalClock::Execute()
{
	Check(this);
	Check(numericDisplay);
	Check(application);

	// HACK!!!
	// Something subtle and mysterious is happening here...
	//...and ONLY in the OPT version (which won't show source in the debugger!)
	//
	// If I try to fold the 'GetSecondsRemainingInGame()' call
	// into the 'Draw' method, the clock will show an extra
	// 60 seconds in the game!
	// Perhaps some invisible type conversion is occurring.

	Scalar
		seconds_remaining = application->GetSecondsRemainingInGame();
	numericDisplay->Draw(&localView, seconds_remaining);
	Check_Fpu();
}


//###########################################################################
// BackgroundConfig
//###########################################################################
Logical
	MakeConfig(
		int /*display_port_index*/,
		Vector2DOf<int> /*position*/,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = MakeConfigMethodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeInteger);// port
	parameterList[1].CheckIt(ParameterDescription::typeString); // name
	parameterList[2].CheckIt(ParameterDescription::typeInteger);// rotation
	parameterList[3].CheckIt(ParameterDescription::typeInteger);// bits
	parameterList[4].CheckIt(ParameterDescription::typeString);	// palette ID
	parameterList[5].CheckIt(ParameterDescription::typeString); // channel ID
	parameterList[6].CheckIt(ParameterDescription::typeString); // palette name
#	endif

	Test_Tell("BackgroundConfig::Make\n");

	char
		*palette_type = parameterList[4].data.string,
		*enable_type = parameterList[5].data.string,
		*palette_name = parameterList[6].data.string;

	//-------------------------------------------------
	// Get palette ID type
	//-------------------------------------------------
	int
		palette_ID = configurePalettes[0].Search(palette_type);

	if (palette_ID < 0)
	{
		DEBUG_STREAM <<
			"configure palette_ID '" << palette_type << "' NOT FOUND\n";
		return False;
	}

	//-------------------------------------------------
	// Get channel enable type
	//-------------------------------------------------
	int
		enable_ID = configureChannels[0].Search(enable_type);

	if (enable_ID < 0)
	{
		DEBUG_STREAM <<
			"configure enable_ID '" << enable_type << "' NOT FOUND\n";
		return False;
	}

	int
		port_number = parameterList[0].data.integer;
	const char
		*port_name =  parameterList[1].data.string;
	int
		rotation =    parameterList[2].data.integer;
	int
		new_bits =    parameterList[3].data.integer;

	Logical
		ignore_palette_flag = (stricmp(palette_name, "NULL") == 0);
	//------------------------------------------------------------
	// Get, lock pixelmap from warehouse
	//------------------------------------------------------------
	//Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	Palette8
		*palette;

	if (ignore_palette_flag)
	{
		palette = NULL;
	}
	else
	{
		palette = warehouse->palette8Bin.Get(palette_name);
		if (palette == NULL)
		{
			DEBUG_STREAM <<
				"MakeConfig missing palette '" << palette_name << "'\n";
			Check_Fpu();
			return False;
		}
		Check(palette);
	}
	//-------------------------------------------------
	// Build the port
	//-------------------------------------------------
	//Check(renderer);
	((L4GaugeRenderer *)gauge_renderer)->BuildGraphicsPort(
		port_number,
		port_name,
		rotation,
		new_bits,
		(SVGA16::PaletteID) palette_ID,
		(L4GraphicsPort::ChannelEnableID) enable_ID,
		palette
	);
	//-------------------------------------------------
	// Release the palette (we're done with it)
	//-------------------------------------------------
	if (!ignore_palette_flag)
	{
		warehouse->palette8Bin.Release(palette_name);
	}

	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("MakeConfig OK\n");
	Check_Fpu();
	return True;
}

MethodDescription
	MakeConfigMethodDescription =
		{
			"configure",
			MakeConfig,
			{
				{ ParameterDescription::typeInteger, NULL }, // graphicsPort #
				{ ParameterDescription::typeString,  NULL }, // name
				{ ParameterDescription::typeInteger, NULL }, // rotation
				{ ParameterDescription::typeInteger, NULL }, // bits
				{ ParameterDescription::typeString,  NULL }, // palette ID
				{ ParameterDescription::typeString,  NULL }, // channel ID
				{ ParameterDescription::typeString,  NULL }, // palette name
				PARAMETER_DESCRIPTION_END
			}
		};

//###########################################################################
// MakeExternConfig
//###########################################################################
Logical
	MakeExternConfig(
		int /*display_port_index*/,
		Vector2DOf<int> /*position*/,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = MakeExternConfigMethodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeInteger);// port #
	parameterList[1].CheckIt(ParameterDescription::typeString); // name
	parameterList[2].CheckIt(ParameterDescription::typeInteger);// bits
#	endif

	Test_Tell("MakeExternConfig\n");

	//-------------------------------------------------
	// Build the port
	//-------------------------------------------------
	//Check(renderer);
	((L4GaugeRenderer *)gauge_renderer)->BuildExternalGraphicsPort(
		parameterList[0].data.integer,		// int port_number,
		parameterList[1].data.string,			// const char *name,
		parameterList[2].data.integer			// int bitAllocation
	);

	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("MakeExternConfig OK\n");
	Check_Fpu();
	return True;
}

MethodDescription
	MakeExternConfigMethodDescription =
		{
			"externalConfigure",
			MakeExternConfig,
			{
				{ ParameterDescription::typeInteger, NULL }, 	// graphicsPort #
				{ ParameterDescription::typeString,  NULL }, 	// name
				{ ParameterDescription::typeInteger, NULL }, 	// bits
				PARAMETER_DESCRIPTION_END
			}
		};

//###########################################################################
// BackgroundReconfig
//###########################################################################
MethodDescription
	BackgroundReconfig::methodDescription =
		{
			"reconfigure",
			BackgroundReconfig::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },// mode mask
				{ ParameterDescription::typeInteger, NULL }, // graphicsPort #
				{ ParameterDescription::typeString,  NULL }, // palette ID
				{ ParameterDescription::typeString,  NULL }, // channel ID
				{ ParameterDescription::typeString,  NULL }, // palette
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundReconfig::Make(
		int /*display_port_index*/,
		Vector2DOf<int> /*position*/,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeInteger);// port #
	parameterList[2].CheckIt(ParameterDescription::typeString);	// palette ID
	parameterList[3].CheckIt(ParameterDescription::typeString); // channel ID
	parameterList[4].CheckIt(ParameterDescription::typeString); // palette name
#	endif

	Test_Tell("BackgroundReconfig::Make\n");

	char
		*palette_type = parameterList[2].data.string,
		*enable_type = parameterList[3].data.string,
		*palette_name = parameterList[4].data.string;

	//-------------------------------------------------
	// Get palette ID type
	//-------------------------------------------------
	int
		palette_ID = configurePalettes[0].Search(palette_type);

	if (palette_ID < 0)
	{
		DEBUG_STREAM <<
			"reconfigure palette_ID '" << palette_type << "' NOT FOUND\n";
		return False;
	}

	//-------------------------------------------------
	// Get channel enable type
	//-------------------------------------------------
	int
		enable_ID = configureChannels[0].Search(enable_type);

	if (enable_ID < 0)
	{
		DEBUG_STREAM <<
			"reconfigure enable_ID '" << enable_type << "' NOT FOUND\n";
		return False;
	}

	//-------------------------------------------------
	// Create object
	//-------------------------------------------------
	BackgroundReconfig
		*bg =
			new BackgroundReconfig(
				parameterList[0].data.modeMask,		// mode mask
				(L4GaugeRenderer *) gauge_renderer,
				parameterList[1].data.integer,		// port #
				palette_ID,
				enable_ID,
				palette_name								// palette name
			);

	Register_Object(bg);

	//-----------------------------------------------------------
	// Make sure the palette was properly placed in the warehouse
	//-----------------------------------------------------------
	if (!bg->ignorePaletteFlag)
	{
		Check(gauge_renderer);
		L4Warehouse
			*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
		Check(warehouse);

		if (warehouse->bitMapBin.Get(palette_name) == NULL)
		{
			DEBUG_STREAM <<
				"BackgroundReconfig missing palette '" << palette_name << "'\n";
			Check_Fpu();
			return False;
		}
		else
		{
			warehouse->bitMapBin.Release(palette_name);
		}
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("BackgroundReconfig::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundReconfig::BackgroundReconfig(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	int port_number,
	int palette_ID,
	int enable_ID,
	const char *palette_name,
	const char *identification_string
):
	GaugeBackground(
		mode_mask,
		renderer,
		0,
		identification_string
	)
{
	portNumber = port_number;
	paletteID = palette_ID;
	enableID = enable_ID;
	paletteName = nameCopy(palette_name);
	ignorePaletteFlag = (stricmp(paletteName, "NULL") == 0);
			 
	//----------------------------------------------------------
	// Preload the palette
	//----------------------------------------------------------
#	if defined(PRELOAD_ART)
		if (!ignorePaletteFlag)
		{
			Check(renderer);
			L4Warehouse
				*warehouse = (L4Warehouse *) renderer->warehousePointer;
			Check(warehouse);

			warehouse->palette8Bin.Get(paletteName);
		}
#	endif

	Check_Fpu();
}

BackgroundReconfig::~BackgroundReconfig()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		if (!ignorePaletteFlag)
		{
			Check(renderer);
			L4Warehouse
				*warehouse = (L4Warehouse *) renderer->warehousePointer;
			Check(warehouse);

			warehouse->palette8Bin.Release(paletteName);
		}
#	endif
	//------------------------------------------------------------
	// Delete the names
	//------------------------------------------------------------
	Unregister_Pointer(paletteName);
	delete[] paletteName;
	paletteName = NULL;

	Check_Fpu();
}

void
	BackgroundReconfig::BecameActive()
{
	Check(this);
	//------------------------------------------------------------
	// Get, lock pixelmap from warehouse
	//------------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;
	Check(warehouse);

	Palette8
		*palette;

	if (ignorePaletteFlag)
	{
		palette = NULL;
	}
	else
	{
		palette = warehouse->palette8Bin.Get(paletteName);
		Check(palette);
	}
	//-------------------------------------------------
	// Remap the port
	//-------------------------------------------------
	Check(renderer);
	((L4GaugeRenderer *)renderer)->RemapGraphicsPort(
		portNumber,	// int port_number,
		(SVGA16::PaletteID) paletteID,
		(L4GraphicsPort::ChannelEnableID) enableID,
		palette
	);
	//-------------------------------------------------
	// Release the palette (we're done with it)
	//-------------------------------------------------
	if (!ignorePaletteFlag)
	{
		warehouse->palette8Bin.Release(paletteName);
	}
	Check_Fpu();
}

//###########################################################################
// BackgroundLine
//###########################################################################
MethodDescription
	BackgroundLine::methodDescription =
		{
			"bgLine",
			BackgroundLine::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeInteger, NULL },		// 1=thick
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeColor, NULL },		// color
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundLine::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeInteger);	// thick
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeColor);		// color
#	endif

	Test_Tell("BackgroundLine::Make\n");

#	if DEBUG_LEVEL > 0
	BackgroundLine
		*bg =
#	endif
			new BackgroundLine(
				parameterList[0].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				parameterList[1].data.integer,	// thick
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.color
			);

	Register_Object(bg);

	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("BackgroundLine::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundLine::BackgroundLine(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int thick_flag,
	int left, int bottom, int right, int top,
	int color,
	const char *identification_string
):
	GraphicGaugeBackground(
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{

	endpoints.bottomLeft.x = left;
	endpoints.bottomLeft.y = bottom;
	endpoints.topRight.x = right;
	endpoints.topRight.y = top;

	thickFlag = thick_flag;

	localView.SetColor(color);
	Check_Fpu();
}

void
	BackgroundLine::BecameActive()
{
	Check(this);
	//---------------------------------------------
	// Draw it
	//---------------------------------------------
	localView.MoveToAbsolute(endpoints.bottomLeft.x, endpoints.bottomLeft.y);

	if (thickFlag)
	{
		localView.DrawThickLineToAbsolute(
			endpoints.topRight.x, endpoints.topRight.y
		);
	}
	else
	{
		localView.DrawLineToAbsolute(
			endpoints.topRight.x, endpoints.topRight.y
		);
	}
	Check_Fpu();
}

//###########################################################################
// BackgroundRect
//###########################################################################
MethodDescription
	BackgroundRect::methodDescription =
		{
			"bgRect",
			BackgroundRect::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeColor, NULL },		// color
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundRect::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[2].CheckIt(ParameterDescription::typeColor);		// color
#	endif

	Test_Tell("BackgroundRect::Make\n");

#	if DEBUG_LEVEL > 0
	BackgroundRect
		*bg =
#	endif
			new BackgroundRect(
				parameterList[0].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[1].data.vector.x, 
				position.y + parameterList[1].data.vector.y,
				parameterList[2].data.color
			);

	Register_Object(bg);

	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("BackgroundRect::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundRect::BackgroundRect(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int top, int right,
	int color,
	const char *identification_string
):
	GraphicGaugeBackground(
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{

	endpoints.bottomLeft.x = left;
	endpoints.bottomLeft.y = bottom;
	endpoints.topRight.x = right;
	endpoints.topRight.y = top;

	localView.SetColor(color);
	Check_Fpu();
}

void
	BackgroundRect::BecameActive()
{
	Check(this);
	//---------------------------------------------
	// Draw it
	//---------------------------------------------
	localView.MoveToAbsolute(
		endpoints.bottomLeft.x, endpoints.bottomLeft.y
	);
	localView.DrawRectangleToAbsolute(
		endpoints.topRight.x, endpoints.topRight.y
	);
	Check_Fpu();
}

//###########################################################################
// BackgroundFilledRect
//###########################################################################
MethodDescription
	BackgroundFilledRect::methodDescription =
		{
			"bgFilledRect",
			BackgroundFilledRect::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeColor, NULL },		// color
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundFilledRect::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[2].CheckIt(ParameterDescription::typeColor);		// color
#	endif

	Test_Tell("BackgroundFilledRect::Make\n");

	BackgroundFilledRect
		*bg =
			new BackgroundFilledRect(
				parameterList[0].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[1].data.vector.x, 
				position.y + parameterList[1].data.vector.y,
				parameterList[2].data.color
			);

	Register_Object(bg);

	//---------------------------------------------------------------
	// Everything's ok: if 'always active', run once and then kill it
	//---------------------------------------------------------------
	if (
		parameterList[0].data.modeMask ==
		(ModeMask) ModeManager::ModeAlwaysActive
	)
	{
		bg->BecameActive();

		Unregister_Object(bg);
		delete bg;
	}
	Test_Tell("BackgroundFilledRect::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundFilledRect::BackgroundFilledRect(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int top, int right,
	int color,
	const char *identification_string
):
	GraphicGaugeBackground(
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{

	endpoints.bottomLeft.x = left;
	endpoints.bottomLeft.y = bottom;
	endpoints.topRight.x = right;
	endpoints.topRight.y = top;

	localView.SetColor(color);
	Check_Fpu();
}

void
	BackgroundFilledRect::BecameActive()
{
	Check(this);
	//---------------------------------------------
	// Draw it
	//---------------------------------------------
	localView.MoveToAbsolute(
		endpoints.bottomLeft.x, endpoints.bottomLeft.y
	);
	localView.DrawFilledRectangleToAbsolute(
		endpoints.topRight.x, endpoints.topRight.y
	);
	Check_Fpu();
}

//###########################################################################
// BackgroundPixelMap
//###########################################################################
MethodDescription
	BackgroundPixelmap::methodDescription =
		{
			"bgPixelMap",
			BackgroundPixelmap::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeString, NULL },		// pixelmap name
				{ ParameterDescription::typeInteger, NULL },		// 1=opaque
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundPixelmap::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeString);		// map name
	parameterList[2].CheckIt(ParameterDescription::typeInteger);	// opaque
#	endif

	Test_Tell("BackgroundPixelmap::Make\n");

	const char
		*name = parameterList[1].data.string;

	BackgroundPixelmap
		*bg =
			new BackgroundPixelmap(
				parameterList[0].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				name,										//font name
				parameterList[2].data.integer
			);

	Register_Object(bg);

	//--------------------------------------------------------
	// Make sure the map was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->pixelMap8Bin.Get(name) == NULL)
	{
		DEBUG_STREAM <<
			"BackgroundPixelmap::Missing image '" << name << "\n";
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->pixelMap8Bin.Release(name);
	}

	//---------------------------------------------------------------
	// Everything's ok: if 'always active', run once and then kill it
	//---------------------------------------------------------------
	if (
		parameterList[0].data.modeMask ==
		(ModeMask) ModeManager::ModeAlwaysActive
	)
	{
		bg->BecameActive();

		Unregister_Object(bg);
		delete bg;
	}
	Test_Tell("BackgroundPixelmap::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundPixelmap::BackgroundPixelmap(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom,
	const char *pixelmap_name,
	int opaque_flag,
	const char *identification_string
):
	GraphicGaugeBackground(
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	//------------------------------------------------------------
	// Save the map name
	//------------------------------------------------------------
	pixelMapName = nameCopy(pixelmap_name);
	opaqueFlag = opaque_flag;
	//------------------------------------------------------------
	// Set origin
	//------------------------------------------------------------
	localView.SetOrigin(left, bottom);
	//------------------------------------------------------------
	// Order the font from the warehouse (pre-load for future use)
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		L4Warehouse
			*warehouse = (L4Warehouse *) renderer->warehousePointer;
		Check(warehouse);

		Check_Pointer(pixelMapName);
		warehouse->pixelMap8Bin.Get(pixelMapName);
#	endif

	Check_Fpu();
}

BackgroundPixelmap::~BackgroundPixelmap()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		L4Warehouse
			*warehouse = (L4Warehouse *) renderer->warehousePointer;
		Check(warehouse);

		Check_Pointer(pixelMapName);
		warehouse->pixelMap8Bin.Release(pixelMapName);
#	endif
	//------------------------------------------------------------
	// Delete the map name
	//------------------------------------------------------------
	Unregister_Pointer(pixelMapName);
	delete[] pixelMapName;
	pixelMapName = NULL;

	Check_Fpu();
}

Logical
	BackgroundPixelmap::TestInstance() const
{
	Check_Pointer(pixelMapName);
	return GraphicGaugeBackground::TestInstance();
}

void
	BackgroundPixelmap::BecameActive()
{
	Check(this);
	//---------------------------------------------
	// Get the image
	//---------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;
	Check(warehouse);

	PixelMap8
		*map = warehouse->pixelMap8Bin.Get(pixelMapName);

	//---------------------------------------------
	// Draw it
	//---------------------------------------------
	if (map != NULL)
	{
		Check(map);
		localView.MoveToAbsolute(0,0);
		localView.DrawPixelMap8(opaqueFlag, 0, map);
	}
	//---------------------------------------------
	// Release the image
	//---------------------------------------------
	Check(warehouse);
	warehouse->pixelMap8Bin.Release(pixelMapName);
	Check_Fpu();
}

//###########################################################################
// BackgroundBitMap
//###########################################################################
MethodDescription
	BackgroundBitmap::methodDescription =
		{
			"bgBitMap",
			BackgroundBitmap::Make,
			{
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeString, NULL },		// bitmap name
				{ ParameterDescription::typeInteger, NULL },		// 1=opaque
				{ ParameterDescription::typeColor, NULL },		// fg color
				{ ParameterDescription::typeColor, NULL },		// bg color(opaque)
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BackgroundBitmap::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[1].CheckIt(ParameterDescription::typeString);		// map name
	parameterList[2].CheckIt(ParameterDescription::typeInteger);	// opaque
	parameterList[3].CheckIt(ParameterDescription::typeColor);		// fg color
	parameterList[4].CheckIt(ParameterDescription::typeColor);		// bg color
#	endif

	Test_Tell("BackgroundBitMap::Make\n");

	const char
		*name = parameterList[1].data.string;

	BackgroundBitmap
		*bg =
			new BackgroundBitmap(
				parameterList[0].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				name,										//font name
				parameterList[2].data.integer,
				parameterList[3].data.color,
				parameterList[4].data.color
			);

	Register_Object(bg);

	//--------------------------------------------------------
	// Make sure the map was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(name) == NULL)
	{
		DEBUG_STREAM <<
			"BackgroundBitmap::Missing image '" << name << "\n";
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(name);
	}

	//---------------------------------------------------------------
	// Everything's ok: if 'always active', run once and then kill it
	//---------------------------------------------------------------
	if (
		parameterList[0].data.modeMask ==
		(ModeMask) ModeManager::ModeAlwaysActive
	)
	{
		bg->BecameActive();

		Unregister_Object(bg);
		delete bg;
	}
	Test_Tell("BackgroundBitmap::Make OK\n");
	Check_Fpu();
	return True;
}

BackgroundBitmap::BackgroundBitmap(
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom,
	const char *bitmap_name,
	int opaque_flag,
	int fg_color,
	int bg_color,
	const char *identification_string
):
	GraphicGaugeBackground(
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	//------------------------------------------------------------
	// Save the map name
	//------------------------------------------------------------
	bitMapName = nameCopy(bitmap_name);
	opaqueFlag = opaque_flag;
	foregroundColor = fg_color;
	backgroundColor = bg_color;
	//------------------------------------------------------------
	// Set origin
	//------------------------------------------------------------
	localView.SetOrigin(left, bottom);
	//------------------------------------------------------------
	// Order the map from the warehouse (pre-load for future use)
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		L4Warehouse
			*warehouse = (L4Warehouse *) renderer->warehousePointer;
		Check(warehouse);

		Check_Pointer(bitMapName);
		warehouse->bitMapBin.Get(bitMapName);
#	endif

	Check_Fpu();
}

BackgroundBitmap::~BackgroundBitmap()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		L4Warehouse
			*warehouse = (L4Warehouse *) renderer->warehousePointer;
		Check(warehouse);

		Check_Pointer(bitMapName);
		warehouse->bitMapBin.Release(bitMapName);
#	endif
	//------------------------------------------------------------
	// Delete the map name
	//------------------------------------------------------------
	Unregister_Pointer(bitMapName);
	delete[] bitMapName;
	bitMapName = NULL;

	Check_Fpu();
}

Logical
	BackgroundBitmap::TestInstance() const
{
	Check_Pointer(bitMapName);
	return GraphicGaugeBackground::TestInstance();
}

void
	BackgroundBitmap::BecameActive()
{
	Check(this);
	//---------------------------------------------
	// Get the image
	//---------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;
	Check(warehouse);

	BitMap
		*map = warehouse->bitMapBin.Get(bitMapName);

	//---------------------------------------------
	// Draw it
	//---------------------------------------------
	if (map != NULL)
	{
		Check(map);
		localView.MoveToAbsolute(0,0);
		localView.SetColor(foregroundColor);

		if (opaqueFlag)
		{
			localView.DrawBitMapOpaque(backgroundColor, 0, map);
		}
		else
		{
			localView.DrawBitMap(0, map);
		}
	}
	//---------------------------------------------
	// Release the image
	//---------------------------------------------
	Check(warehouse);
	warehouse->pixelMap8Bin.Release(bitMapName);
	Check_Fpu();
}

//###########################################################################
// RankAndScore
//###########################################################################

#define RNSCHARWIDTH 6
#define RNSCHARHEIGHT 8
#define RNSSCOREDIGITS 8
#define RNSRANK_X 2
#define RNSLINE_X  (RNSRANK_X+RNSCHARWIDTH+2)
#define RNSSCORE_X (RNSLINE_X+2)
#define RNS_Y 2
#define RNSWIDTH  (2+RNSCHARWIDTH+5+(RNSCHARWIDTH*RNSSCOREDIGITS)+2)
#define RNSHEIGHT (2+RNSCHARHEIGHT+2)

MethodDescription
	RankAndScore::methodDescription =
		{
			"rankAndScore",
			RankAndScore::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	RankAndScore::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeString);	// font
	parameterList[3].CheckIt(ParameterDescription::typeColor);	// background
	parameterList[4].CheckIt(ParameterDescription::typeColor);	// foreground
#	endif

	Test_Tell("RankAndScore::Make\n");

#	if DEBUG_LEVEL > 0
	RankAndScore
		*rank_and_score =
#	endif
			new RankAndScore(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 												//unsigned int owner_ID
				display_port_index, 							//int graphics_port_number
				position.x, position.y,
				parameterList[2].data.string,				//font name
				parameterList[3].data.integer,			//int background_color
				parameterList[4].data.integer				//int foreground_color
			);

	Register_Object(rank_and_score);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL)
	{
		Test_Tell("RankAndScore::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[2].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("RankAndScore::Make OK\n");
	Check_Fpu();
	return True;
}

RankAndScore::RankAndScore(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom,
	const char *font_name,
	int foreground_color, int background_color,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	Check(renderer);
	//
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	//
	numericDisplayRank = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		RNSRANK_X,RNS_Y,
		font_name,
		1,
		NumericDisplay::unsignedFormat,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplayRank);

	numericDisplayScore = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		RNSSCORE_X,RNS_Y,
		font_name,
		RNSSCOREDIGITS,
		NumericDisplay::signedBlankedZerosFormat,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplayScore);

	localView.SetPositionWithinPort(
		left,bottom,
		left+RNSWIDTH+1,bottom+RNSHEIGHT+1
	);

	linkedEntity = NULL;
	foregroundColor = foreground_color;
	backgroundColor = background_color;

	Check_Fpu();
}

RankAndScore::~RankAndScore()
{
	Check(this);

	if (linkedEntity != NULL)
	{
		Player
			*player;

		Check(linkedEntity);
		player = linkedEntity->GetPlayerLink();
		Check(player);
		//---------------------------------------
		// Truncate the score (no rounding)
		//---------------------------------------
		DEBUG_STREAM <<
			"~RankAndScore: I think my score is " <<
			(int)(player->currentScore) << "\n";
	}

	if (numericDisplayRank != NULL)
	{
		Unregister_Object(numericDisplayRank);
		delete numericDisplayRank;
		numericDisplayRank = NULL;
	}
	if (numericDisplayScore != NULL)
	{
		Unregister_Object(numericDisplayScore);
		delete numericDisplayScore;
		numericDisplayScore = NULL;
	}

	Check_Fpu();
}

Logical
	RankAndScore::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	RankAndScore::ShowInstance(char */*indent*/)
{
}

void
	RankAndScore::BecameActive()
{
	Check(this);

	previousState = False;

	Check(numericDisplayRank);
	Check(numericDisplayScore);

	numericDisplayRank->ForceUpdate();
	numericDisplayScore->ForceUpdate();

	Check_Fpu();
}

void
	RankAndScore::LinkToEntity(Entity *entity)
{
	Test_Tell("RankAndScore::LinkToEntity\n" << std::flush);
	Check(this);

	linkedEntity = entity;
	Check_Fpu();
}

void
	RankAndScore::Execute()
{
	Check(this);
	Check(numericDisplayRank);
	Check(numericDisplayScore);

	Check(application);
	Logical
		currentState =
			(application->GetApplicationState() == Application::RunningMission);

	if (previousState != currentState)
	{
		previousState = currentState;

		if (currentState == True)
		{
			//-------------------------------------------
			// Draw background
			//-------------------------------------------
			localView.SetColor(backgroundColor);
			localView.MoveToAbsolute(1,1);
			localView.DrawFilledRectangleToAbsolute(RNSWIDTH-1,RNSHEIGHT-1);

			localView.SetColor(foregroundColor);
			localView.MoveToAbsolute(0,0);
			localView.DrawRectangleToAbsolute(RNSWIDTH,RNSHEIGHT);
			localView.MoveToAbsolute(RNSLINE_X,0);
			localView.DrawLineToAbsolute(RNSLINE_X,RNSHEIGHT);
		}
	}

	if (currentState == True)
	{
		//-------------------------------------------
		// Get 'our' placement
		//-------------------------------------------
		if (linkedEntity != NULL)
		{
			Player
				*player;

			Check(linkedEntity);
			player = linkedEntity->GetPlayerLink();
			Check(player);
			//---------------------------------------
			// Truncate the score (no rounding)
			//---------------------------------------
			int
				integer_score = (int)(player->currentScore);
			//---------------------------------------
			// Update displays
			//---------------------------------------
			numericDisplayRank->Draw(
				&localView,
				player->playerRanking+1
			);
			numericDisplayScore->Draw(
				&localView,
				(Scalar) integer_score
			);
		}
	}
	Check_Fpu();
}

//###########################################################################
// WipeGaugeScalar
//###########################################################################
WipeGaugeScalar::WipeGaugeScalar(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	Direction direction,
	Scalar min,
	Scalar max,
	const char *identification_string
):
	GraphicGauge(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	// graphics_port may be NULL!
	//
	//-----------------------------------------------------------
	// Initialize internal values
	//-----------------------------------------------------------
	//
	width = right - left - 1;
	height = top - bottom - 1;
	Verify(width >= 0);
	Verify(height >= 0);

	previousValue = -1234;
	previousSize.MakeEmpty();

	wipeDirection = direction;
	minimumValue = min;
	maximumValue = max - min;
	Verify(maximumValue != 0);

	localView.SetPositionWithinPort(left, bottom, right, top);

	Check_Fpu();
}


WipeGaugeScalar::~WipeGaugeScalar()
{
	Check(this);

	// base class deletes all connections in Gauge::~Gauge
	Check_Fpu();
}

Logical
	WipeGaugeScalar::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	WipeGaugeScalar::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "WipeGaugeScalar:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "previousSize      =" << previousSize << "\n";
	GraphicGauge::ShowInstance(temp);
	Check_Fpu();
}

void
	WipeGaugeScalar::BecameActive()
{
	Check(this);
	forceUpdateFlag = True;
	Check_Fpu();
}

void
	WipeGaugeScalar::Execute()
{
	Check(this);

	int
		new_value;

	Scalar
		q;

	Rectangle2D
		rectangle;

	//
	//-----------------------------------------------------------
	// Calculate new_value
	//-----------------------------------------------------------
	//
	if (currentValue < minimumValue)
	{
		currentValue = minimumValue;
	}

	currentValue -= minimumValue;

	if (currentValue > maximumValue)
	{
		currentValue = maximumValue;
	}

   Verify(maximumValue != 0);
	q = currentValue / maximumValue;

	if (q > 1.0)
	{
		q = 1.0;
	}
	else if (q < -1.0)
	{
		q = -1.0;
	}
	//
	//-----------------------------------------------------------
	// Update display
	//-----------------------------------------------------------
	//
	switch(wipeDirection)
	{
	case wipeLeft:
		new_value = width - (int) (width*q + .5);
		
		if (forceUpdateFlag)
		{
			forceUpdateFlag = False;

			rectangle.topRight.x   = width;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = new_value;
			rectangle.bottomLeft.y = 0;

			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}

			rectangle.topRight.x   = new_value-1;
			rectangle.bottomLeft.x = 0;

			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (new_value > previousValue)
		{
			rectangle.topRight.x   = new_value-1;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = previousValue;
			rectangle.bottomLeft.y = 0;
			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (previousValue > new_value)
		{
			rectangle.topRight.x   = previousValue-1;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = new_value;
			rectangle.bottomLeft.y = 0;
			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}
			previousValue = new_value;
		}
		break;

	case wipeDown:
		new_value = height - (int) (height*q + .5);
		
		if (forceUpdateFlag)
		{
			forceUpdateFlag = False;

			rectangle.topRight.x   = width;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = new_value;

			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}

			rectangle.topRight.y   = new_value-1;
			rectangle.bottomLeft.y = 0;

			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (new_value > previousValue)
		{
			rectangle.topRight.x   = width;
			rectangle.topRight.y   = new_value+1;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = previousValue;
			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (previousValue > new_value)
		{
			rectangle.topRight.x   = width;
			rectangle.topRight.y   = previousValue+1;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = new_value;
			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}
			previousValue = new_value;
		}
		break;

	case wipeRight:
		new_value = (int) (width*q + .5);
		
		if (forceUpdateFlag)
		{
			forceUpdateFlag = False;

			rectangle.topRight.x   = new_value;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = 0;

			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}

			rectangle.topRight.x   = width;
			rectangle.bottomLeft.x = new_value+1;

			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (new_value > previousValue)
		{
			rectangle.topRight.x   = new_value;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = previousValue+1;
			rectangle.bottomLeft.y = 0;
			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (previousValue > new_value)
		{
			rectangle.topRight.x   = previousValue;
			rectangle.topRight.y   = height;
			rectangle.bottomLeft.x = new_value+1;
			rectangle.bottomLeft.y = 0;
			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		break;

	case wipeUp:
		new_value = (int) (height*q + .5);
		
		if (forceUpdateFlag)
		{
			forceUpdateFlag = False;

			rectangle.topRight.x   = width;
			rectangle.topRight.y   = new_value;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = 0;

			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}

			rectangle.topRight.y   = height;
			rectangle.bottomLeft.y = new_value+1;

			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (previousValue < new_value)
		{
			rectangle.topRight.x   = width;
			rectangle.topRight.y   = new_value;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = previousValue;
			if (!rectangle.IsEmpty())
			{
				DrawActive(&rectangle);
			}
			previousValue = new_value;
		}
		else if (previousValue > new_value)
		{
			rectangle.topRight.x   = width;
			rectangle.topRight.y   = previousValue;
			rectangle.bottomLeft.x = 0;
			rectangle.bottomLeft.y = new_value;
			if (!rectangle.IsEmpty())
			{
				DrawInactive(&rectangle);
			}
			previousValue = new_value;
		}
		break;
	}
	Check_Fpu();
}

void
	WipeGaugeScalar::DrawActive(
		Rectangle2D */*rectangle*/
	)
{
	Fail("WipeGaugeScalar::DrawActive is not overridden");
}

void
	WipeGaugeScalar::DrawInactive(
		Rectangle2D */*rectangle*/
	)
{
	Fail("WipeGaugeScalar::DrawInactive is not overridden");
}

//###########################################################################
// BarGraphSolidScalar
//###########################################################################
MethodDescription
	BarGraphSolidScalar::methodDescription =
		{
			"solidbar",
			BarGraphSolidScalar::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeColor, NULL },		// foreground
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeString, NULL },		// direction
				{ ParameterDescription::typeScalar, NULL },		// min
				{ ParameterDescription::typeScalar, NULL },		// max
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BarGraphSolidScalar::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeColor);		// foreground
	parameterList[4].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[5].CheckIt(ParameterDescription::typeString);		// direction
	parameterList[6].CheckIt(ParameterDescription::typeScalar);		// min
	parameterList[7].CheckIt(ParameterDescription::typeScalar);		// max
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);	// attribute
#	endif

	Test_Tell("BarGraphSolidScalar::Make\n");

	int
		direction = configureDirection[0].Search(
			parameterList[5].data.string
		);

	if (direction < 0)
	{
		Test_Tell("BarGraphSolidScalar::Make direction NOT FOUND\n");
		Check_Fpu();
		return False;
	} 

#	if DEBUG_LEVEL > 0
	BarGraphSolidScalar
		*bar_graph =
#	endif
			 new BarGraphSolidScalar(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										// unsigned int owner_ID
				display_port_index, 					// int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.color,		// int foreground_color
				parameterList[4].data.color,		// int background_color
				(WipeGaugeScalar::Direction) direction,
				parameterList[6].data.scalar,		//	Scalar min,
				parameterList[7].data.scalar,		//	Scalar max,
				(Scalar *) parameterList[8].data.attributePointer // Scalar *valptr
			// HACK!!!! The (Scalar *) is VERY dangerous!
			);

	Register_Object(bar_graph);

	Test_Tell("BarGraphSolidScalar::Make OK\n");
	Check_Fpu();
	return True;
}

BarGraphSolidScalar::BarGraphSolidScalar(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	int foreground_color, int background_color,
	WipeGaugeScalar::Direction direction,
	Scalar min,
	Scalar max,
	Scalar *value_pointer,
	const char *identification_string
):
	WipeGaugeScalar(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		left, bottom, right, top,
		direction,
		min,
		max,
		identification_string
	)
{
	backgroundColor = background_color;
	foregroundColor = foreground_color;

	//
	//-----------------------------------------------------------
	// Build connection to value
	// (if NULL, it's assumed that a derived object built the
	// connection for us)
	//-----------------------------------------------------------
	//
	if (value_pointer != NULL)
	{
		GaugeConnection
			*connection = new
				GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
		Register_Object(connection);
		AddConnection(connection);
	}
	Check_Fpu();
}

BarGraphSolidScalar::~BarGraphSolidScalar()
{
	Check(this);
	Check_Fpu();
}

Logical
	BarGraphSolidScalar::TestInstance() const
{
	return WipeGaugeScalar::TestInstance();
}

void
	BarGraphSolidScalar::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "BarGraphSolidScalar:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "foregroundColor=" << foregroundColor << "\n";
	std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
	WipeGaugeScalar::ShowInstance(temp);
	Check_Fpu();
}

void
	BarGraphSolidScalar::DrawActive(
		Rectangle2D *rectangle
	)
{
	localView.SetColor(foregroundColor);
	localView.MoveToAbsolute(
		rectangle->bottomLeft.x,
		rectangle->bottomLeft.y
	);
	localView.DrawFilledRectangleToAbsolute(
		rectangle->topRight.x,
		rectangle->topRight.y
	);
	Check_Fpu();
}

void
	BarGraphSolidScalar::DrawInactive(
		Rectangle2D *rectangle
	)
{
	localView.SetColor(backgroundColor);
	localView.MoveToAbsolute(
		rectangle->bottomLeft.x,
		rectangle->bottomLeft.y
	);
	localView.DrawFilledRectangleToAbsolute(
		rectangle->topRight.x,
		rectangle->topRight.y
	);
	Check_Fpu();
}


//###########################################################################
// BarGraphBitMapScalar
//###########################################################################
MethodDescription
	BarGraphBitMapScalar::methodDescription =
		{
			"bitmapbar",
			BarGraphBitMapScalar::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// bit map name
				{ ParameterDescription::typeColor,  NULL },		// foreground
				{ ParameterDescription::typeColor,  NULL },		// background
				{ ParameterDescription::typeString, NULL },		// direction
				{ ParameterDescription::typeScalar, NULL },		// min
				{ ParameterDescription::typeScalar, NULL },		// max
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BarGraphBitMapScalar::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);	// size
	parameterList[3].CheckIt(ParameterDescription::typeString);	// image name
	parameterList[4].CheckIt(ParameterDescription::typeColor);	// foreground
	parameterList[5].CheckIt(ParameterDescription::typeColor);	// background
	parameterList[6].CheckIt(ParameterDescription::typeString);	// direction
	parameterList[7].CheckIt(ParameterDescription::typeScalar);	// min
	parameterList[8].CheckIt(ParameterDescription::typeScalar);	// max
	parameterList[9].CheckIt(ParameterDescription::typeAttribute);
#	endif

	Test_Tell("BarGraphBitMapScalar::Make\n");

	int
		direction = configureDirection[0].Search(
			parameterList[6].data.string
		);

	if (direction < 0)
	{
		Test_Tell("BarGraphBitMapScalar::Make direction NOT FOUND\n");
		Check_Fpu();
		return False;
	} 

#	if DEBUG_LEVEL > 0
	BarGraphBitMapScalar
		*bar_graph =
#	endif
			new BarGraphBitMapScalar(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 														// owner_ID*/
				display_port_index, 									// graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,						// BitMap name
				parameterList[4].data.color,						// int fg_color
				parameterList[5].data.color,						// int bg_color
				(WipeGaugeScalar::Direction) direction,
				parameterList[7].data.scalar,						//	Scalar min,
				parameterList[8].data.scalar,						//	Scalar max,
				(Scalar *) parameterList[9].data.attributePointer// Scalar *val_ptr
				// HACK!!!! The (Scalar *) is VERY dangerous!
		);

	Register_Object(bar_graph);
	//---------------------------------------------------------
	// Make sure the image was properly placed in the warehouse
	//---------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("BarGraphBitMapScalar::Missing bitmap\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("BarGraphBitMapScalar::Make OK\n");
	Check_Fpu();
	return True;
}

BarGraphBitMapScalar::BarGraphBitMapScalar(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *bitmap_name,		//BitMap *bit_map,
	int foreground_color, int background_color,
	WipeGaugeScalar::Direction direction,
	Scalar min,
	Scalar max,
	Scalar *value_pointer,
	const char *identification_string
):
	WipeGaugeScalar(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		left, bottom, right, top,
		direction,
		min,
		max,
		identification_string
	)
{
	//------------------------------------------------------------
	// Save the bitmap name
	//------------------------------------------------------------
	bitMapName = nameCopy(bitmap_name);
	//-------------------------------------------------------------
	// Save colors
	//-------------------------------------------------------------
	backgroundColor = background_color;
	foregroundColor = foreground_color;
	//-------------------------------------------------------------
	// Order the image from the warehouse (pre-load for future use)
	//-------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);

		((L4Warehouse *)renderer->warehousePointer)->bitMapBin.Get(bitMapName);
#	endif
	//-----------------------------------------------------------
	// Build connection to value
	// (if NULL, it's assumed that a derived object built the
	// connection for us)
	//-----------------------------------------------------------
	if (value_pointer != NULL)
	{
		GaugeConnection
			*connection = new
				GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
		Register_Object(connection);
		AddConnection(connection);
	}
	Check_Fpu();
}

BarGraphBitMapScalar::~BarGraphBitMapScalar()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);
		((L4Warehouse *)renderer->warehousePointer)->
			bitMapBin.Release(bitMapName);
#	endif
	//------------------------------------------------------------
	// Delete the bitmap name
	//------------------------------------------------------------
	Unregister_Pointer(bitMapName);
	delete[] bitMapName;
	bitMapName = NULL;

	Check_Fpu();
}

Logical
	BarGraphBitMapScalar::TestInstance() const
{
	return WipeGaugeScalar::TestInstance();
}

void
	BarGraphBitMapScalar::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "BarGraphBitMapScalar:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "bitMapName=     " << bitMapName << "\n";
	std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
	WipeGaugeScalar::ShowInstance(temp);
	Check_Fpu();
}

void
	BarGraphBitMapScalar::DrawActive(
		Rectangle2D *rectangle
	)
{
	//-----------------------------------------------------------
	// Get and lock the image so that we may use it
	//-----------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;

	Check_Pointer(bitMapName);
	BitMap
		*bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName);
	//-----------------------------------------------------------
	// Draw the image
	//-----------------------------------------------------------
	if (bit_map != NULL)
	{
		Check(bit_map);
		localView.SetColor(foregroundColor);

		localView.MoveToAbsolute(
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y
		);

		localView.DrawBitMapOpaque(
			backgroundColor,
			0,			// rotation
			bit_map,
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y,
			rectangle->topRight.x,
			rectangle->topRight.y
		);
	}
	//-----------------------------------------------------------
	// Unlock the image: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->bitMapBin.Release(bitMapName);

	Check_Fpu();
}

void
	BarGraphBitMapScalar::DrawInactive(
		Rectangle2D *rectangle
	)
{
	Check(this);

	localView.SetColor(backgroundColor);

	localView.MoveToAbsolute(
		rectangle->bottomLeft.x,
		rectangle->bottomLeft.y
	);

	localView.DrawFilledRectangleToAbsolute(
		rectangle->topRight.x,
		rectangle->topRight.y
	);

	Check_Fpu();
}

//###########################################################################
// BarGraphPixelMapScalar
//###########################################################################
MethodDescription
	BarGraphPixelMapScalar::methodDescription =
		{
			"pixelbar",
			BarGraphPixelMapScalar::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// pixel map name
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeString, NULL },		// direction
				{ ParameterDescription::typeScalar, NULL },		// min
				{ ParameterDescription::typeScalar, NULL },		// max
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	BarGraphPixelMapScalar::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);	// size
	parameterList[3].CheckIt(ParameterDescription::typeString);	// foreground
	parameterList[4].CheckIt(ParameterDescription::typeColor);	// background
	parameterList[5].CheckIt(ParameterDescription::typeString);	// direction
	parameterList[6].CheckIt(ParameterDescription::typeScalar);	// min
	parameterList[7].CheckIt(ParameterDescription::typeScalar);	// max
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);
#	endif

	Test_Tell("BarGraphPixelMapScalar::Make\n");

	int
		direction = configureDirection[0].Search(
			parameterList[5].data.string
		);

	if (direction < 0)
	{
		Test_Tell("BarGraphPixelMapScalar::Make direction NOT FOUND\n");
		Check_Fpu();
		return False;
	} 

#	if DEBUG_LEVEL > 0
	BarGraphPixelMapScalar
		*bar_graph =
#	endif
			new BarGraphPixelMapScalar(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 														// owner_ID*/
				display_port_index, 									// graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x, 
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,						// PixelMap name
				parameterList[4].data.color,						// int bg_color
				(WipeGaugeScalar::Direction) direction,
				parameterList[6].data.scalar,						//	Scalar min,
				parameterList[7].data.scalar,						//	Scalar max,
				(Scalar *) parameterList[8].data.attributePointer	//Scalar *valptr
				// HACK!!!! The (Scalar *) is VERY dangerous!
			);

	Register_Object(bar_graph);
	//---------------------------------------------------------
	// Make sure the image was properly placed in the warehouse
	//---------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("BarGraphPixelMapScalar::Missing pixelmap\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("BarGraphPixelMapScalar::Make OK\n");
	Check_Fpu();
	return True;
}

BarGraphPixelMapScalar::BarGraphPixelMapScalar(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *pixelmap_name,			//PixelMap8 *pixel_map,
	int background_color,
	WipeGaugeScalar::Direction direction,
	Scalar min,
	Scalar max,
	Scalar *value_pointer,
	const char *identification_string
):
	WipeGaugeScalar(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		left, bottom, right, top,
		direction,
		min,
		max,
		identification_string
	)
{
	//-------------------------------------------------------------
	// Make local copy of map name
	//-------------------------------------------------------------
	Check_Pointer(pixelmap_name);
	pixelMapName = nameCopy(pixelmap_name);
	Check_Pointer(pixelMapName);
	//-------------------------------------------------------------
	// Save background color
	//-------------------------------------------------------------
	backgroundColor = background_color;
	//-------------------------------------------------------------
	// Order the image from the warehouse (pre-load for future use)
	//-------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);

		((L4Warehouse *) renderer->warehousePointer)->
			pixelMap8Bin.Get(pixelMapName);
#	endif
	//-----------------------------------------------------------
	// Build connection to value
	// (if NULL, it's assumed that a derived object built the
	// connection for us)
	//-----------------------------------------------------------
	//
	if (value_pointer != NULL)
	{
		GaugeConnection
			*connection = new
				GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
		Register_Object(connection);
		AddConnection(connection);
	}
	Check_Fpu();
}

BarGraphPixelMapScalar::~BarGraphPixelMapScalar()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded image
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(pixelMapName);

		((L4Warehouse *) renderer->warehousePointer)->
			pixelMap8Bin.Get(pixelMapName);
#	endif
	//------------------------------------------------------------
	// Delete the map name
	//------------------------------------------------------------
	Unregister_Pointer(pixelMapName);
	delete[] pixelMapName;
	pixelMapName = NULL;

	Check_Fpu();
}

Logical
	BarGraphPixelMapScalar::TestInstance() const
{
	return WipeGaugeScalar::TestInstance();
}

void
	BarGraphPixelMapScalar::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "BarGraphPixelMapScalar:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	std::cout << temp << "pixelMapName=   " << pixelMapName << "\n";
	std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
	WipeGaugeScalar::ShowInstance(temp);
	Check_Fpu();
}

void
	BarGraphPixelMapScalar::DrawActive(
		Rectangle2D *rectangle
	)
{
	//-----------------------------------------------------------
	// Get and lock the image so that we may use it
	//-----------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;

	Check_Pointer(pixelMapName);
	PixelMap8
		*pixel_map = renderer->warehousePointer->pixelMap8Bin.Get(pixelMapName);
	//-----------------------------------------------------------
	// Draw the image
	//-----------------------------------------------------------
	if (pixel_map != NULL)
	{
		Check(pixel_map);

		localView.MoveToAbsolute(
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y
		);

		localView.DrawPixelMap8(
			False,	// opaque,
			0,			// rotation
			pixel_map,
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y,
			rectangle->topRight.x,
			rectangle->topRight.y
		);
	}
	//-----------------------------------------------------------
	// Unlock the image: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->pixelMap8Bin.Release(pixelMapName);

	Check_Fpu();
}

void
	BarGraphPixelMapScalar::DrawInactive(
		Rectangle2D *rectangle
	)
{
	//-----------------------------------------------------------
	// Get and lock the image so that we may use it
	//-----------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;

	Check_Pointer(pixelMapName);
	PixelMap8
		*pixel_map = renderer->warehousePointer->pixelMap8Bin.Get(pixelMapName);
	//-----------------------------------------------------------
	// Draw the image
	//-----------------------------------------------------------
	if (pixel_map != NULL)
	{
		Check(pixel_map);

		localView.SetColor(backgroundColor);

		localView.MoveToAbsolute(
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y
		);

		localView.DrawPixelMap8SingleColor(
			0,			// rotation
			pixel_map,
			rectangle->bottomLeft.x,
			rectangle->bottomLeft.y,
			rectangle->topRight.x,
			rectangle->topRight.y
		);
	}
	//-----------------------------------------------------------
	// Unlock the image: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->pixelMap8Bin.Release(pixelMapName);

	Check_Fpu();
}

//#######################################################################
// ColorState
//#######################################################################
MethodDescription
	ColorState::methodDescription=
		{
			"colorState",
			ColorState::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeString, NULL },		// bitmap name
				{ ParameterDescription::typeColor, NULL },		// color 0
				{ ParameterDescription::typeScalar, NULL },		// 0...a
				{ ParameterDescription::typeColor, NULL },		// color 1
				{ ParameterDescription::typeScalar, NULL },		// a...b
				{ ParameterDescription::typeColor, NULL },		// color 2
				{ ParameterDescription::typeScalar, NULL },		// b...c
				{ ParameterDescription::typeColor, NULL },		// color 3
				{ ParameterDescription::typeScalar, NULL },		// c...d
				{ ParameterDescription::typeColor, NULL },		// color 4 (+)
				{ ParameterDescription::typeInteger, NULL },		// zone #
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	ColorState::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeString);	// bitmap name
	parameterList[3].CheckIt(ParameterDescription::typeColor);	// first color
	parameterList[4].CheckIt(ParameterDescription::typeScalar);	// first range
	parameterList[5].CheckIt(ParameterDescription::typeColor);	// second color
	parameterList[6].CheckIt(ParameterDescription::typeScalar);	// second range
	parameterList[7].CheckIt(ParameterDescription::typeColor);	// third color
	parameterList[8].CheckIt(ParameterDescription::typeScalar);	// third range
	parameterList[9].CheckIt(ParameterDescription::typeColor);	// fourth color
	parameterList[10].CheckIt(ParameterDescription::typeScalar);// fourth range
	parameterList[11].CheckIt(ParameterDescription::typeColor);	// fifth color
	parameterList[12].CheckIt(ParameterDescription::typeInteger);	// zone #
	parameterList[13].CheckIt(ParameterDescription::typeAttribute);
#	endif

	Test_Tell("ColorState::Make\n");

#	if DEBUG_LEVEL > 0
	ColorState
		*color_state =
#	endif
			new ColorState(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										// unsigned int owner_ID
				display_port_index, 					// int graphics_port_number
				position.x, position.y,
				parameterList[2].data.string,
				parameterList[3].data.color,
				parameterList[4].data.scalar,
				parameterList[5].data.color,
				parameterList[6].data.scalar,
				parameterList[7].data.color,
				parameterList[8].data.scalar,
				parameterList[9].data.color,
				parameterList[10].data.scalar,
				parameterList[11].data.color,
				parameterList[12].data.integer,
				(DamageZone ***) parameterList[13].data.attributePointer
				// HACK!!!! The cast above is VERY dangerous!
			);

	Register_Object(color_state);
	//---------------------------------------------------------
	// Make sure the image was properly placed in the warehouse
	//---------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL)
	{
		Test_Tell("ColorState::Missing pixelmap\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[2].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("ColorState::Make OK\n");
	Check_Fpu();
	return True;
}

ColorState::ColorState(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom,
	const char *bitmap_name,
	int first_color,
	Scalar first_bin,
	int second_color,
	Scalar second_bin,
	int third_color,
	Scalar third_bin,
	int fourth_color,
	Scalar fourth_bin,
	int fifth_color,
	int zone_number,
	DamageZone ***value_pointer,
	const char *identification_string
):
	GraphicGauge(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Test_Tell("ColorState creator\n" << std::flush);
	Check(renderer);
	//------------------------------------------------------------
	// Save the map name
	//------------------------------------------------------------
	bitMapName = nameCopy(bitmap_name);
	//-------------------------------------------------------------
	// Order the image from the warehouse (pre-load for future use)
	//-------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);

		((L4Warehouse *)renderer->warehousePointer)->
			bitMapBin.Get(bitMapName);
#	endif
	//-------------------------------------------------------------
	// Initialize values
	//-------------------------------------------------------------
	localView.SetOrigin(left, bottom);

	color[0] = first_color;
	color[1] = second_color;
	color[2] = third_color;
	color[3] = fourth_color;
	color[4] = fifth_color;

	bin[0] = first_bin;
	bin[1] = second_bin;
	bin[2] = third_bin;
	bin[3] = fourth_bin;

	Test_Tell("value_pointer=" << value_pointer << "\n" << std::flush);
	Check_Pointer(value_pointer);
	DamageZone
		**array_pointer = *value_pointer;
	Test_Tell("array_pointer=" << array_pointer << "\n" << std::flush);
	Check_Pointer(array_pointer);

	Test_Tell("zone_number=" << zone_number << "\n" << std::flush);
	damagePointer = array_pointer[zone_number];
	Test_Tell("damagePointer=" << damagePointer << "\n" << std::flush);
	Check(damagePointer);

	Check_Fpu();
}

ColorState::~ColorState()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);
		((L4Warehouse *)renderer->warehousePointer)->
			bitMapBin.Release(bitMapName);
#	endif
	//------------------------------------------------------------
	// Delete the map name
	//------------------------------------------------------------
	Unregister_Pointer(bitMapName);
	delete[] bitMapName;
	bitMapName = NULL;

	Check_Fpu();
}

Logical
	ColorState::TestInstance() const
{
	return True;
}

void
	ColorState::ShowInstance(char */*indent*/)
{
	Check_Fpu();
}

void
	ColorState::BecameActive()
{
	Check(this);

	previousState = -1;
}

void
	ColorState::Execute()
{
	Check(this);

	//-----------------------------------------------------------
	// Get and lock the image so that we may use it
	//-----------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;

	Check_Pointer(bitMapName);
	BitMap
		*bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName);
	//-----------------------------------------------------------
	// Draw the image
	//-----------------------------------------------------------
	if (bit_map != NULL)
	{
		Check(bit_map);
		Check(damagePointer);
		Scalar
			value(damagePointer->damageLevel);
		int
			i;
		//----------------------------------------
		// Find current bin
		//----------------------------------------
		for(i=0; i<4; ++i)
		{
			if (value < bin[i])
			{
				break;
			}
		}
		//----------------------------------------
		// If different, draw it
		//----------------------------------------
		if (i != previousState)
		{
			previousState = i;

			localView.SetColor(color[i]);
			localView.DrawBitMap(0, bit_map);
		}
	}
	//-----------------------------------------------------------
	// Unlock the image: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->bitMapBin.Release(bitMapName);

	Check_Fpu();
}

//#######################################################################
// TwoState
//#######################################################################
MethodDescription
	TwoState::methodDescription=
		{
			"twoState",
			TwoState::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeString, NULL },		// bitmap name
				{ ParameterDescription::typeColor, NULL },		// color 0
				{ ParameterDescription::typeColor, NULL },		// color 1
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	TwoState::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeString);	// bitmap name
	parameterList[3].CheckIt(ParameterDescription::typeColor);	// first color
	parameterList[4].CheckIt(ParameterDescription::typeColor);	// second color
	parameterList[5].CheckIt(ParameterDescription::typeAttribute);
#	endif

	Test_Tell("TwoState::Make\n");

#	if DEBUG_LEVEL > 0
	TwoState
		*two_state =
#	endif
			new TwoState(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				parameterList[2].data.string,		//bitmap name
				parameterList[3].data.color,
				parameterList[4].data.color,
				(int *) parameterList[5].data.attributePointer
				// HACK!!!! The cast above is VERY dangerous!
			);

	Register_Object(two_state);
	//---------------------------------------------------------
	// Make sure the image was properly placed in the warehouse
	//---------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL)
	{
		Test_Tell("TwoState::Missing bitmap\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[2].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("TwoState::Make OK\n");
	Check_Fpu();
	return True;
}

TwoState::TwoState(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom,
	const char *bitmap_name,
	int first_color,
	int second_color,
	int *value_pointer,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Test_Tell("TwoState creator\n" << std::flush);
	Check_Pointer(this);

	//------------------------------------------------------------
	// Save the bitmap name
	//------------------------------------------------------------
	bitMapName = nameCopy(bitmap_name);
	//-------------------------------------------------------------
	// Order the image from the warehouse (pre-load for future use)
	//-------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);

		((L4Warehouse *)renderer->warehousePointer)->
			bitMapBin.Get(bitMapName);
#	endif
	//-----------------------------------------------------------
	// Initialize values
	//-----------------------------------------------------------
	localView.SetOrigin(left, bottom);

	color[0] = first_color;
	color[1] = second_color;
	//-----------------------------------------------------------
	// Build connection to value
	//-----------------------------------------------------------
	GaugeConnection
		*connection;

	connection = new
		GaugeConnectionDirectOf<int>(0, &currentValue, value_pointer);
	Register_Object(connection);
	AddConnection(connection);

	Check_Fpu();
}

TwoState::~TwoState()
{
	Check(this);
	//------------------------------------------------------------
	// Unlock preloaded art
	//------------------------------------------------------------
#	if defined(PRELOAD_ART)
		Check(renderer);
		Check(renderer->warehousePointer);
		Check_Pointer(bitMapName);
		((L4Warehouse *)renderer->warehousePointer)->
			bitMapBin.Release(bitMapName);
#	endif
	//------------------------------------------------------------
	// Delete the bitmap name
	//------------------------------------------------------------
	Unregister_Pointer(bitMapName);
	delete[] bitMapName;
	bitMapName = NULL;

	Check_Fpu();
}

Logical
	TwoState::TestInstance() const
{
	return True;
}

void
	TwoState::ShowInstance(char */*indent*/)
{
	Check_Fpu();
}

void
	TwoState::BecameActive()
{
	Check(this);
	previousState = -1;
	Check_Fpu();
}

void
	TwoState::Execute()
{
	Check(this);
	//-----------------------------------------------------------
	// Get and lock the image so that we may use it
	//-----------------------------------------------------------
	Check(renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) renderer->warehousePointer;

	Check_Pointer(bitMapName);
	BitMap
		*bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName);
	//-----------------------------------------------------------
	// Draw the image
	//-----------------------------------------------------------
	if (bit_map != NULL)
	{
		Check(bit_map);

		int
			new_value;

		if (currentValue > 0)
		{
			new_value = 1;
		}
		else
		{
			new_value = 0;
		}

		if (new_value != previousState)
		{
			previousState = new_value;

			localView.SetColor(color[new_value]);
			localView.DrawBitMap(0, bit_map);
		}
	}
	//-----------------------------------------------------------
	// Unlock the image: we're done
	//-----------------------------------------------------------
	Check(warehouse);
	warehouse->bitMapBin.Release(bitMapName);

	Check_Fpu();
}

//###########################################################################
// NumericDisplayScalarTwoState
//###########################################################################
MethodDescription
	NumericDisplayScalarTwoState ::methodDescription =
		{
			"numericIntegerTwoState",
			NumericDisplayScalarTwoState::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeVector, NULL },		// size
				{ ParameterDescription::typeString, NULL },		// font name
				{ ParameterDescription::typeInteger, NULL },		// # of digits
				{ ParameterDescription::typeString, NULL },		// format
				{ ParameterDescription::typeColor, NULL },		// background
				{ ParameterDescription::typeColor, NULL },		// foreground
				{ ParameterDescription::typeAttribute, NULL },	// attribute for number
				{ ParameterDescription::typeAttribute, NULL },   // attribute for logical
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	NumericDisplayScalarTwoState::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeVector);		// size
	parameterList[3].CheckIt(ParameterDescription::typeString);		// font
	parameterList[4].CheckIt(ParameterDescription::typeInteger);	// # of digs
	parameterList[5].CheckIt(ParameterDescription::typeString);		// format
	parameterList[6].CheckIt(ParameterDescription::typeColor);		// background
	parameterList[7].CheckIt(ParameterDescription::typeColor);		// foreground
	parameterList[8].CheckIt(ParameterDescription::typeAttribute);	// value name
	parameterList[9].CheckIt(ParameterDescription::typeAttribute); // second value name
#	endif

	Test_Tell("NumericDisplayScalarTwoState::Make\n");

	int
		number_format = configureFormat[0].Search(
			parameterList[5].data.string
		);

	if (number_format < 0)
	{
		Test_Tell("NumericDisplayScalarTwoState::Make format NOT FOUND\n");
		Check_Fpu();
		return False;
	}

#	if DEBUG_LEVEL > 0
	NumericDisplayScalarTwoState
		*numeric_display =
#	endif
			new NumericDisplayScalarTwoState(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										//unsigned int owner_ID
				display_port_index, 					//int graphics_port_number
				position.x, position.y,
				position.x + parameterList[2].data.vector.x,
				position.y + parameterList[2].data.vector.y,
				parameterList[3].data.string,		//font name
				parameterList[4].data.integer,	//int number_of_chars
				(NumericDisplay::NumericFormat) number_format,
				parameterList[6].data.integer,	//int background_color
				parameterList[7].data.integer,	//int foreground_color
				(Scalar *) parameterList[8].data.attributePointer,
				(int *) parameterList[9].data.attributePointer  // second (logical) value
				// HACK!!!! The (Scalar *) is VERY dangerous!
				// HACK!!!! The (int *) is VERY dangerous!
			);
	Register_Object(numeric_display);

	//--------------------------------------------------------
	// Make sure the font was properly placed in the warehouse
	//--------------------------------------------------------
	Check(gauge_renderer);
	L4Warehouse
		*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
	Check(warehouse);

	if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL)
	{
		Test_Tell("NumericDisplayScalarTwoState::Missing font\n");
		Check_Fpu();
		return False;
	}
	else
	{
		warehouse->bitMapBin.Release(parameterList[3].data.string);
	}
	//--------------------------------------------------------
	// Everything's ok
	//--------------------------------------------------------
	Test_Tell("NumericDisplayScalarTwoState::Make OK\n");
	Check_Fpu();
	return True;
}

NumericDisplayScalarTwoState::NumericDisplayScalarTwoState(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int left, int bottom, int right, int top,
	const char *font_name,
	int number_of_digits,
	NumericDisplay::NumericFormat requested_format,
	int background_color, int foreground_color,
	Scalar *value_pointer,
	int *logical_pointer,
	const char *identification_string
):
	GraphicGauge(
		rate,
		mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Check_Pointer(this);
	// graphics_port may be NULL!
	Check_Pointer(value_pointer);
	Check(renderer);
	//-----------------------------------------------------------
	// Set internal values
	//-----------------------------------------------------------
	numericDisplay = new NumericDisplay(
		(L4Warehouse *) renderer->warehousePointer,
		0,0,
		font_name,
		number_of_digits,
		requested_format,
		background_color,
		foreground_color
	);
	Register_Object(numericDisplay);

	localView.SetPositionWithinPort(left, bottom, right, top);

	color[0] = background_color;
	color[1] = foreground_color;
	//-----------------------------------------------------------
	// Build connection to value
	//-----------------------------------------------------------
	GaugeConnection
		*value_connection;

	GaugeConnection
		*logical_connection;

	value_connection = new
		GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
	Register_Object(value_connection);
	AddConnection(value_connection);


	logical_connection = new
		GaugeConnectionDirectOf<int>(0, &currentLogical, logical_pointer);
	Register_Object(logical_connection);
	AddConnection(logical_connection);

   previousValue = currentValue;
	Check_Fpu();
}

NumericDisplayScalarTwoState::~NumericDisplayScalarTwoState()
{
	Check(this);

	if (numericDisplay != NULL)
	{
		Unregister_Object(numericDisplay);
		delete numericDisplay;
		numericDisplay = NULL;
	}

	// base class deletes all connections in Gauge::~Gauge
	Check_Fpu();
}

Logical
	NumericDisplayScalarTwoState::TestInstance() const
{
	return GraphicGauge::TestInstance();
}

void
	NumericDisplayScalarTwoState::ShowInstance(char *indent)
{
	Check(this);

	std::cout << indent << "NumericDisplayScalarTwoState:\n";

	char
		temp[80];

	Str_Copy(temp,indent, 80);
	Str_Cat(temp,"...", 80);

	GraphicGauge::ShowInstance(temp);
	Check(numericDisplay);
	numericDisplay->ShowInstance(temp);
	Check_Fpu();
}

void
	NumericDisplayScalarTwoState::BecameActive()
{
	Check(this);
	Check(numericDisplay);
	previousState = -1;
	numericDisplay->ForceUpdate();
	Check_Fpu();
}

#if 0
void
	NumericDisplayScalarTwoState::SetColors(int bg_color, int fg_color)
{
	Check(this);
	numericDisplay->SetColors(bg_color, fg_color);
	Check_Fpu();
}
#endif

void
	NumericDisplayScalarTwoState::Execute()
{
	Check(this);
	Check(numericDisplay);

	int new_logical;
	if (currentLogical > 0)
	{
		new_logical = 1;
	}
	else
	{
		new_logical = 0;
	}

	// Draw if state has changed.  NumericDisplay only redraws if value has changed
	if (new_logical != previousState || currentValue != previousValue)
	{
		previousState = new_logical;
      previousValue = currentValue;
		if (currentLogical > 0)
		{
			numericDisplay->Draw(&localView,currentValue);
		}
		else
		{
			numericDisplay->Erase(&localView);
		}
	}
	Check_Fpu();
}



//#######################################################################
// SegmentArc
//#######################################################################
SegmentArc::SegmentArc(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int center_x, int center_y,
	Scalar inner0, Scalar outer0,
	Scalar inner1, Scalar outer1,
	Scalar deg0, Scalar deg1,
	int number_of_segs_and_direction,
	int background_color,
	int foreground_color,
	Logical use_thick_lines,
	const char *identification_string
) :
	GraphicGauge(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		identification_string
	)
{
	Test_Tell("SegmentArc creator\n" << std::flush);
	Check_Pointer(this);


	backgroundColor = background_color;
	foregroundColor = foreground_color;
	numberOfSegments = number_of_segs_and_direction;
	startAngle = deg0*(2.0*M_PI)/360;
	innerRadius = inner0;
	outerRadius = outer0;
	useThickLines = use_thick_lines;

	if (numberOfSegments < 0)
	{
		numberOfSegments = - numberOfSegments;
	}
	Verify(numberOfSegments > 0);

	Scalar
		total_angle = (deg1*(2.0*M_PI)/360) - startAngle;

	if (number_of_segs_and_direction > 0)
	{
		if (total_angle < 0.0)
		{
			total_angle += (2.0*M_PI);
		}
	}
	else
	{
		if (total_angle > 0.0)
		{
			total_angle -= (2.0*M_PI);
		}
	}
	deltaAngle       = (total_angle)/numberOfSegments;
	deltaInnerRadius = (inner1 - inner0)/numberOfSegments;
	deltaOuterRadius = (outer1 - outer0)/numberOfSegments;

	localView.SetOrigin(center_x, center_y);

	Check_Fpu();
}

SegmentArc::~SegmentArc()
{

	// base class deletes all connections in Gauge::~Gauge
	Check_Fpu();
}

Logical
	SegmentArc::TestInstance() const
{
	return True;
}

void
	SegmentArc::ShowInstance(char */*indent*/)
{

	std::cout << "SegmentArc\n";
	std::cout << "   backgroundColor  = " << backgroundColor << "\n";
	std::cout << "   foregroundColor  = " << foregroundColor << "\n";
	std::cout << "   numberOfSegments = " << numberOfSegments << "\n";
	std::cout << "   startAngle       = " << startAngle << "\n";
	std::cout << "   deltaAngle       = " << deltaAngle << "\n";
	std::cout << "   deltaInnerRadius = " << deltaInnerRadius << "\n";
	std::cout << "   deltaOuterRadius = " << deltaOuterRadius << "\n";
	std::cout << "   previousSegment  = " << previousSegment << "\n";
	Check_Fpu();
}

void
	SegmentArc::BecameActive()
{
	Check(this);

	previousSegment = 0;
}

void
	SegmentArc::Execute()
{
	Check(this);

	if (currentValue < (Scalar) 0)
	{
		currentValue = (Scalar) 0;
	}
	else if (currentValue > (Scalar) 1)
	{
		currentValue = (Scalar) 1;
	}

	Verify(numberOfSegments > 0);

	int
		i,
		new_segment = (int) (currentValue * numberOfSegments + .5);
	Scalar
		inner_radius,
		delta_inner,
		outer_radius,
		delta_outer,
		segment_angle,
		delta_angle,
		segment_sin,
		segment_cos;

	if (new_segment != previousSegment)
	{
		if (new_segment > previousSegment)
		{
			localView.SetColor(foregroundColor);

			i = new_segment - previousSegment;	// how many segments

			inner_radius = innerRadius + (previousSegment * deltaInnerRadius);
			outer_radius = outerRadius + (previousSegment * deltaOuterRadius);
			segment_angle = startAngle + (previousSegment * deltaAngle);
		}
		else
		{
			localView.SetColor(backgroundColor);

			i = previousSegment - new_segment;	// how many segments

			inner_radius = innerRadius + (new_segment * deltaInnerRadius);
			outer_radius = outerRadius + (new_segment * deltaOuterRadius);
			segment_angle = startAngle + (new_segment * deltaAngle);
		}

		delta_outer = deltaOuterRadius;
		delta_inner = deltaInnerRadius;
		delta_angle = deltaAngle;

		for(; i>=0; --i)
		{
			segment_sin = sin(segment_angle);
			segment_cos = cos(segment_angle);

			localView.MoveToAbsolute(
				(int)(segment_sin*inner_radius + .5),
				(int)(segment_cos*inner_radius + .5)
			);

			if (useThickLines)
			{
				localView.DrawThickLineToAbsolute(
					(int)(segment_sin*outer_radius + .5),
					(int)(segment_cos*outer_radius + .5)
				);
			}
			else
			{
				localView.DrawLineToAbsolute(
					(int)(segment_sin*outer_radius + .5),
					(int)(segment_cos*outer_radius + .5)
				);
			}

			inner_radius += delta_inner;
			outer_radius += delta_outer;
			segment_angle += delta_angle;
		}

		previousSegment = new_segment;
	}
	Check_Fpu();
}

//#######################################################################
// SegmentArcNormalized
//#######################################################################
MethodDescription
	SegmentArcNormalized::methodDescription =
		{
			"segmentArc",
			SegmentArcNormalized::Make,
			{
				{ ParameterDescription::typeRate, NULL },			// rate ID
				{ ParameterDescription::typeModeMask, NULL },	// mode mask
				{ ParameterDescription::typeScalar, NULL },		// inner 0
				{ ParameterDescription::typeScalar, NULL },		// outer 0
				{ ParameterDescription::typeScalar, NULL },		// inner 1
				{ ParameterDescription::typeScalar, NULL },		// outer 1
				{ ParameterDescription::typeScalar, NULL },		// deg 0
				{ ParameterDescription::typeScalar, NULL },		// deg 1
				{ ParameterDescription::typeInteger, NULL },		// segs
				{ ParameterDescription::typeColor, NULL },		// fg
				{ ParameterDescription::typeColor, NULL },		// bg
				{ ParameterDescription::typeAttribute, NULL },	// attribute
				PARAMETER_DESCRIPTION_END
			}
		};

Logical
	SegmentArcNormalized::Make(
		int display_port_index,
		Vector2DOf<int> position,
		Entity */*entity*/,
		GaugeRenderer * gauge_renderer
	)
{
	ParameterDescription
		*parameterList = methodDescription.parameterList;

#	if DEBUG_LEVEL > 0
	parameterList[0].CheckIt(ParameterDescription::typeRate);		// rate ID
	parameterList[1].CheckIt(ParameterDescription::typeModeMask);	// mode mask
	parameterList[2].CheckIt(ParameterDescription::typeScalar);		// inner0
	parameterList[3].CheckIt(ParameterDescription::typeScalar);		// outer0
	parameterList[4].CheckIt(ParameterDescription::typeScalar);		// inner1
	parameterList[5].CheckIt(ParameterDescription::typeScalar);		// outer1
	parameterList[6].CheckIt(ParameterDescription::typeScalar);		// deg0
	parameterList[7].CheckIt(ParameterDescription::typeScalar);		// deg1
	parameterList[8].CheckIt(ParameterDescription::typeInteger);	// segs&dir
	parameterList[9].CheckIt(ParameterDescription::typeColor);		// bg color
	parameterList[10].CheckIt(ParameterDescription::typeColor);		// fg color
	parameterList[11].CheckIt(ParameterDescription::typeAttribute);
#	endif

	Test_Tell("SegmentArcNormalized::Make\n");

#	if DEBUG_LEVEL > 0
	SegmentArcNormalized
		*arc =
#	endif
			new SegmentArcNormalized(
				parameterList[0].data.rate,
				parameterList[1].data.modeMask,
				(L4GaugeRenderer *) gauge_renderer,
				0, 										// unsigned int owner_ID
				display_port_index, 					// int graphics_port_number
				position.x, position.y,
				parameterList[2].data.scalar,		// inner0
				parameterList[3].data.scalar,		// outer0
				parameterList[4].data.scalar,		// inner1
				parameterList[5].data.scalar,		// outer1
				parameterList[6].data.scalar,		// deg0
				parameterList[7].data.scalar,		// deg1
				parameterList[8].data.integer,	// segs & dir
				parameterList[9].data.color,		// bg
				parameterList[10].data.color,		// fg
				(Scalar *) parameterList[11].data.attributePointer,
				True										// use thick lines

				// HACK - cast is VERY DANGEROUS!
			);

	Register_Object(arc);

	Test_Tell("SegmentArcNormalized::Make OK\n");
	Check_Fpu();
	return True;
}

SegmentArcNormalized::SegmentArcNormalized(
	GaugeRate rate,
	ModeMask mode_mask,
	L4GaugeRenderer *renderer,
	unsigned int owner_ID,
	int graphics_port_number,
	int center_x, int center_y,
	Scalar inner0, Scalar outer0,
	Scalar inner1, Scalar outer1,
	Scalar deg0, Scalar deg1,
	int number_of_segs_and_direction,
	int background_color,
	int foreground_color,
	Scalar *value_pointer,
	Logical use_thick_lines,
	const char *identification_string
) :
	SegmentArc(
		rate,
      mode_mask,
		renderer,
		owner_ID,
		graphics_port_number,
		center_x, center_y,
		inner0, outer0,
		inner1, outer1,
		deg0, deg1,
		number_of_segs_and_direction,
		background_color,
		foreground_color,
		use_thick_lines,
		identification_string
	)
{
	Test_Tell("SegmentArcNormalized creator\n" << std::flush);
	Check_Pointer(this);

	//-----------------------------------------------------------
	// Build connection to value
	//-----------------------------------------------------------
	GaugeConnection
		*connection;

	connection = new
		GaugeConnectionDirectOf<Scalar>(0, &currentValue, value_pointer);
	Check(connection);
	Register_Object(connection);

	AddConnection(connection);

	Check_Fpu();
}
