#ifdef PRECOMPILEDHEADERS
	#include "Editor All.h"
#else
	#include "builddefines.h"
#endif

#ifdef JA2EDITOR

#ifndef PRECOMPILEDHEADERS
	#include <stdio.h>
	#include "types.h"
	#include "mousesystem.h"
	#include "Button System.h"
	#include "Font Control.h"
	#include "Isometric Utils.h"
	#include "WorldDat.h"
	#include "Render Dirty.h"
	#include "sysutil.h"
	#include "wordwrap.h"
	#include "environment.h"
	#include "Interface Items.h"
	#include "Soldier Find.h"
	#include "World Items.h"
	#include "Text.h"
	#include "Overhead map.h"
	#include "Cursor Modes.h"
	#include "editscreen.h"
	#include "EditorTerrain.h"
	#include "Cursor Modes.h"
	#include "EditorItems.h"
	#include "EditorMercs.h"
	#include "EditorBuildings.h"
	#include "EditorMapInfo.h"
	#include "EditorDefines.h"
	#include "Editor Taskbar Utils.h"
	#include "Editor Taskbar Creation.h"
	#include "Editor Callback Prototypes.h"
	#include "Editor Modes.h"
	#include "Text Input.h"
	#include "Item Statistics.h"
	#include "Map Information.h"
	#include "Sector Summary.h"
	#include "Item Statistics.h"
	#include "pits.h"
	#include "Soldier Find.h"
	#include "lighting.h"
	#include "Keys.h"
#endif

void RenderEditorInfo();

extern ITEM_POOL *gpItemPool;

//editor icon storage vars 
INT32	giEditMercDirectionIcons[2];
UINT32 guiMercInventoryPanel;
UINT32 guiOmertaMap;
UINT32 guiMercInvPanelBuffers[9];
UINT32 guiMercTempBuffer;
INT32 giEditMercImage[2];
UINT32 guiExclamation;
UINT32 guiKeyImage;

//editor Mouseregion storage vars
MOUSE_REGION TerrainTileButtonRegion[ NUM_TERRAIN_TILE_REGIONS ];
MOUSE_REGION ItemsRegion;
MOUSE_REGION MercRegion;
MOUSE_REGION EditorRegion;

void EnableEditorRegion( INT8 bRegionID )
{
	switch( bRegionID )
	{
		case BASE_TERRAIN_TILE_REGION_ID:
		case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
			MSYS_EnableRegion( &TerrainTileButtonRegion[ bRegionID ] );
			break;
		case ITEM_REGION_ID:
			MSYS_EnableRegion( &ItemsRegion );
			break;
		case MERC_REGION_ID:
			MSYS_EnableRegion( &MercRegion );
			break;
	}
}

void DisableEditorRegion( INT8	bRegionID )
{
	switch( bRegionID )
	{
		case BASE_TERRAIN_TILE_REGION_ID:
		case 1: case 2: case 3: case 4: case 5: case 6: case 7:
			MSYS_DisableRegion( &TerrainTileButtonRegion[ bRegionID ] );
			break;
		case ITEM_REGION_ID:
			MSYS_DisableRegion( &ItemsRegion );
			break;
		case MERC_REGION_ID:
			MSYS_DisableRegion( &MercRegion );
			break;
	}
}

void RemoveEditorRegions()
{
	INT32 x;
	MSYS_RemoveRegion( &EditorRegion );
	for(x = BASE_TERRAIN_TILE_REGION_ID; x < NUM_TERRAIN_TILE_REGIONS; x++ )
	{
		MSYS_RemoveRegion( &TerrainTileButtonRegion[ x ] );
	}
	MSYS_RemoveRegion( &ItemsRegion );
	MSYS_RemoveRegion( &MercRegion );
}

void InitEditorRegions()
{
	INT32 x;

	//By doing this, all of the buttons underneath are blanketed and can't be used anymore.
	//Any new buttons will cover this up as well.  Think of it as a barrier between the editor buttons,
	//and the game's interface panel buttons and regions.
	MSYS_DefineRegion( &EditorRegion, 0, 360, 640, 480, MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );

	//Create the regions for the terrain tile selections
	for( x = 0; x < NUM_TERRAIN_TILE_REGIONS; x++ )
	{
		MSYS_DefineRegion(&TerrainTileButtonRegion[x],(INT16)(261+x*42),369,(INT16)(303+x*42),391,
			MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK,(MOUSE_CALLBACK)TerrainTileButtonRegionCallback);
		MSYS_SetRegionUserData( &TerrainTileButtonRegion[x], 0, x );
		MSYS_DisableRegion( &TerrainTileButtonRegion[x] );
	}
	gfShowTerrainTileButtons=FALSE;

	//Create the region for the items selection window.
	MSYS_DefineRegion( &ItemsRegion, 100, 360, 540, 440, MSYS_PRIORITY_NORMAL, 0, 
		(MOUSE_CALLBACK)MouseMovedInItemsRegion, (MOUSE_CALLBACK)MouseClickedInItemsRegion );
	MSYS_DisableRegion( &ItemsRegion );

	//Create the region for the merc inventory panel.
	MSYS_DefineRegion( &MercRegion, 175, 361, 450, 460, MSYS_PRIORITY_NORMAL, 0, 
		MouseMovedInMercRegion, MouseClickedInMercRegion );
	MSYS_DisableRegion( &MercRegion );
}

void LoadEditorImages()
{
  VOBJECT_DESC    VObjectDesc;

	//Set up the merc inventory panel
	VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
	sprintf( VObjectDesc.ImageFile, "EDITOR\\InvPanel.sti" );
	if( !AddVideoObject( &VObjectDesc, &guiMercInventoryPanel ) )
		AssertMsg( 0, "Failed to load data\\editor\\InvPanel.sti" );
	//Set up small omerta map
	sprintf( VObjectDesc.ImageFile, "EDITOR\\omerta.sti" );
	if( !AddVideoObject( &VObjectDesc, &guiOmertaMap ) )
		AssertMsg( 0, "Failed to load data\\editor\\omerta.sti" );
	//Set up the merc directional buttons.
	giEditMercDirectionIcons[0] = LoadGenericButtonIcon("EDITOR//arrowsoff.sti");
	giEditMercDirectionIcons[1] = LoadGenericButtonIcon("EDITOR//arrowson.sti");

	giEditMercImage[0] = LoadButtonImage("EDITOR\\leftarrow.sti",0,1,2,3,4);
	giEditMercImage[1] = LoadButtonImage("EDITOR\\rightarrow.sti",0,1,2,3,4);

	sprintf( VObjectDesc.ImageFile, "EDITOR\\Exclamation.sti" );
	if( !AddVideoObject( &VObjectDesc, &guiExclamation ) )
		AssertMsg( 0, "Failed to load data\\editor\\Exclamation.sti" );
	sprintf( VObjectDesc.ImageFile, "EDITOR\\KeyImage.sti" );
	if( !AddVideoObject( &VObjectDesc, &guiKeyImage ) )
		AssertMsg( 0, "Failed to load data\\editor\\KeyImage.sti" );
}

void DeleteEditorImages()
{
	//The merc inventory panel
	DeleteVideoObjectFromIndex( guiMercInventoryPanel );
	DeleteVideoObjectFromIndex( guiOmertaMap );
	//The merc directional buttons
	UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[0] );
	UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[1] );

	UnloadButtonImage( giEditMercImage[0] );
	UnloadButtonImage( giEditMercImage[1] );
}

void CreateEditorBuffers()
{

	INT32						i;
	VSURFACE_DESC		vs_desc;
	UINT16					usUselessWidth, usUselessHeight;
	UINT8						ubBitDepth;

	//create buffer for the transition slot for merc items.  This slot contains the newly
	//selected item graphic in it's inventory size version.  This buffer is then scaled down
	//into the associated merc inventory panel slot buffer which is approximately 20% smaller.
	GetCurrentVideoSettings( &usUselessWidth, &usUselessHeight, &ubBitDepth );
	vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
	vs_desc.usWidth = 60;
	vs_desc.usHeight = 25;
	vs_desc.ubBitDepth = ubBitDepth;
	if( !AddVideoSurface( &vs_desc, &guiMercTempBuffer ) )
		AssertMsg( 0, "Failed to allocate memory for merc tempitem buffer." );

	//create the nine buffers for the merc's inventory slots.
	vs_desc.usHeight = MERCINV_SLOT_HEIGHT;
	for( i = 0; i < 9; i++ )
	{
		vs_desc.usWidth = i<3 ? MERCINV_SMSLOT_WIDTH : MERCINV_LGSLOT_WIDTH;
		if( !AddVideoSurface( &vs_desc, &guiMercInvPanelBuffers[i] ) )
			AssertMsg( 0, "Failed to allocate memory for merc item[] buffers." );
	}
}

void DeleteEditorBuffers()
{
	INT32 i;
	DeleteVideoSurfaceFromIndex( guiMercTempBuffer );
	for( i = 0; i < 9; i++ )
	{
		DeleteVideoSurfaceFromIndex( guiMercInvPanelBuffers[ i ] );
	}
}

void ShowEditorToolbar( INT32 iNewTaskMode )
{
	switch( iNewTaskMode )
	{
		case TASK_TERRAIN:		ShowEditorButtons( FIRST_TERRAIN_BUTTON, LAST_TERRAIN_BUTTON );								break;
		case TASK_BUILDINGS:	ShowEditorButtons( FIRST_BUILDINGS_BUTTON, LAST_BUILDINGS_BUTTON );						break;
		case TASK_ITEMS:			ShowEditorButtons( FIRST_ITEMS_BUTTON, LAST_ITEMS_BUTTON );										break;
		case TASK_MERCS:			ShowEditorButtons( FIRST_MERCS_TEAMMODE_BUTTON, LAST_MERCS_TEAMMODE_BUTTON );	break;
		case TASK_MAPINFO:		ShowEditorButtons( FIRST_MAPINFO_BUTTON, LAST_MAPINFO_BUTTON );								break;
		case TASK_OPTIONS:		ShowEditorButtons( FIRST_OPTIONS_BUTTON, LAST_OPTIONS_BUTTON );								break;
		default:		return;
	}
}

void HideEditorToolbar( INT32 iOldTaskMode )
{
	INT32 i, iStart, iEnd;
	switch( iOldTaskMode )
	{
		case TASK_TERRAIN:		iStart = FIRST_TERRAIN_BUTTON;			iEnd = LAST_TERRAIN_BUTTON;			break;
		case TASK_BUILDINGS:	iStart = FIRST_BUILDINGS_BUTTON;		iEnd = LAST_BUILDINGS_BUTTON;		break;
		case TASK_ITEMS:			iStart = FIRST_ITEMS_BUTTON;				iEnd = LAST_ITEMS_BUTTON;				break;
		case TASK_MERCS:			iStart = FIRST_MERCS_BUTTON;				iEnd = LAST_MERCS_BUTTON;				break;
		case TASK_MAPINFO:		iStart = FIRST_MAPINFO_BUTTON;			iEnd = LAST_MAPINFO_BUTTON;		break;
		case TASK_OPTIONS:		iStart = FIRST_OPTIONS_BUTTON;			iEnd = LAST_OPTIONS_BUTTON;			break;
		default:		return;
	}
	for( i = iStart; i <= iEnd; i++ )
	{
		HideButton( iEditorButton[ i ] );
		UnclickEditorButton( i );
	}
}

void CreateEditorTaskbar()
{
	InitEditorRegions();
	LoadEditorImages();
	CreateEditorBuffers();
	CreateEditorTaskbarInternal();
	HideItemStatsPanel();
}

void DeleteEditorTaskbar()
{
	INT32 x;

	iOldTaskMode = iCurrentTaskbar;

	for( x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
		RemoveButton( iEditorButton[ x ] );

	RemoveEditorRegions();
	DeleteEditorImages();
	DeleteEditorBuffers();

}

void DoTaskbar(void)
{
	if(!iTaskMode || iTaskMode == iCurrentTaskbar )
	{
		return;
	}

	gfRenderTaskbar = TRUE;
	
	HideEditorToolbar( iCurrentTaskbar );

	//Special code when exiting previous editor tab
	switch( iCurrentTaskbar )
	{
		case TASK_TERRAIN:
			UnclickEditorButton( TAB_TERRAIN );
			HideTerrainTileButtons();
			break;
		case TASK_BUILDINGS:
			UnclickEditorButton( TAB_BUILDINGS );
			KillTextInputMode();
			break;
		case TASK_ITEMS:
			UnclickEditorButton( TAB_ITEMS );
			HideItemStatsPanel();
			if( eInfo.fActive )
				ClearEditorItemsInfo();
			gfShowPits = FALSE;
			RemoveAllPits();
			break;
		case TASK_MERCS:
			UnclickEditorButton( TAB_MERCS );
			IndicateSelectedMerc( SELECT_NO_MERC );
			SetMercEditingMode( MERC_NOMODE );
			break;
		case TASK_MAPINFO:
			UnclickEditorButton( TAB_MAPINFO );
			ExtractAndUpdateMapInfo();
			KillTextInputMode();
			HideExitGrids();
			break;
		case TASK_OPTIONS:
			UnclickEditorButton( TAB_OPTIONS );
			break;
	}

	//Setup the new tab mode
	iCurrentTaskbar = iTaskMode;
	ShowEditorToolbar( iTaskMode );
	iTaskMode = TASK_NONE;

	//Special code when entering a new editor tab
	switch( iCurrentTaskbar )
	{
		case TASK_MERCS:
			ClickEditorButton( TAB_MERCS );
			ClickEditorButton( MERCS_ENEMY);
			iDrawMode = DRAW_MODE_ENEMY;
			SetMercEditingMode( MERC_TEAMMODE );
			fBuildingShowRoofs = FALSE;
			UpdateRoofsView();
			break;
		case TASK_TERRAIN:
			ClickEditorButton( TAB_TERRAIN );
			ShowTerrainTileButtons();
			SetEditorTerrainTaskbarMode( TERRAIN_FGROUND_TEXTURES );
			break;
		case TASK_BUILDINGS:
			ClickEditorButton( TAB_BUILDINGS );
			if(fBuildingShowRoofs) 
				ClickEditorButton( BUILDING_TOGGLE_ROOF_VIEW );
			if(fBuildingShowWalls)
				ClickEditorButton( BUILDING_TOGGLE_WALL_VIEW );
			if(fBuildingShowRoomInfo)
				ClickEditorButton( BUILDING_TOGGLE_INFO_VIEW );
			if( gfCaves )
			{
				ClickEditorButton( BUILDING_CAVE_DRAWING );
				iDrawMode = DRAW_MODE_CAVES;
			}
			else
			{
				ClickEditorButton( BUILDING_NEW_ROOM );
				iDrawMode = DRAW_MODE_ROOM;
			}
			TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
			SetEditorSmoothingMode( gMapInformation.ubEditorSmoothingType );
			gusSelectionType = gusSavedBuildingSelectionType;
			SetupTextInputForBuildings();
			break;
		case TASK_ITEMS:
			SetFont( FONT10ARIAL );
			SetFontForeground( FONT_YELLOW );
			ClickEditorButton( TAB_ITEMS );
			ClickEditorButton( ITEMS_WEAPONS + eInfo.uiItemType - TBAR_MODE_ITEM_WEAPONS );
			InitEditorItemsInfo( eInfo.uiItemType );
			ShowItemStatsPanel();
			gfShowPits = TRUE;
			AddAllPits();
			iDrawMode = DRAW_MODE_PLACE_ITEM;
			break;
		case TASK_MAPINFO:
			ClickEditorButton( TAB_MAPINFO );
			if ( gfFakeLights )
				ClickEditorButton( MAPINFO_TOGGLE_FAKE_LIGHTS );
			ClickEditorButton( MAPINFO_ADD_LIGHT1_SOURCE );
			iDrawMode = DRAW_MODE_LIGHT;
			TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
			SetupTextInputForMapInfo();
			break;
		case TASK_OPTIONS:
			ClickEditorButton( TAB_OPTIONS );
			TerrainTileDrawMode = TERRAIN_TILES_NODRAW;
			break;
	}
}

//Disables the task bar, but leaves it on screen. Used when a selection window is up.
void DisableEditorTaskbar(void)
{
	INT32 x;
	for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
		DisableButton( iEditorButton[ x ] );
}


void EnableEditorTaskbar(void)
{
	INT32 x;
	
	for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
		EnableButton( iEditorButton[ x ] );
	//Keep permanent buttons disabled.
	DisableButton( iEditorButton[ MERCS_1 ] );
	DisableButton( iEditorButton[ MAPINFO_LIGHT_PANEL ] );
	DisableButton( iEditorButton[ MAPINFO_RADIO_PANEL ] );
	DisableButton( iEditorButton[ ITEMSTATS_PANEL ] );
	DisableButton( iEditorButton[ MERCS_PLAYERTOGGLE ] );
	DisableButton( iEditorButton[ MERCS_PLAYER ] );
	if( iCurrentTaskbar == TASK_ITEMS )
		DetermineItemsScrolling();
}

//A specialized mprint function that'll restore the editor panel underneath the
//string before rendering the string.  This is obviously only useful for drawing text
//in the editor taskbar.
void mprintfEditor(INT16 x, INT16 y, UINT16 *pFontString, ...)
{
	va_list argptr;
	wchar_t	string[512];
	UINT16 uiStringLength, uiStringHeight;

	Assert( pFontString != NULL );

	va_start( argptr, pFontString );       	// Set up variable argument pointer
	vswprintf( string, pFontString, argptr);	// process gprintf string (get output str)
	va_end( argptr );

	uiStringLength = StringPixLength( string, FontDefault );
	uiStringHeight = GetFontHeight( FontDefault );

	ClearTaskbarRegion( x, y, (INT16)(x+uiStringLength), (INT16)(y+uiStringHeight) );
	mprintf( x, y, string );
}

void ClearTaskbarRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
{
	ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, sTop, sRight, sBottom, gusEditorTaskbarColor );

	if( !sLeft )
	{
		ColorFillVideoSurfaceArea( ButtonDestBuffer, 0, sTop, 1, sBottom, gusEditorTaskbarHiColor );
		sLeft++;
	}
	if( sTop == 360 )
	{
		ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 360, sRight, 361, gusEditorTaskbarHiColor );
		sTop++;
	}
	if( sBottom == 480 )
		ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 479, sRight, 480, gusEditorTaskbarLoColor );
	if( sRight == 640 )
		ColorFillVideoSurfaceArea( ButtonDestBuffer, 639, sTop, 640, sBottom, gusEditorTaskbarLoColor );

	InvalidateRegion( sLeft, sTop, sRight, sBottom );
}


//Kris:
//This is a new function which duplicates the older "yellow info boxes" that
//are common throughout the editor.  This draws the yellow box with the indentation
//look.
void DrawEditorInfoBox( UINT16 *str, UINT32 uiFont, UINT16 x, UINT16 y, UINT16 w, UINT16 h )
{
	UINT16 usFillColorDark, usFillColorLight, usFillColorBack;
	UINT16 x2, y2;
	UINT16 usStrWidth;

	x2 = x + w;
	y2 = y + h;

	usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
	usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
	usFillColorBack = Get16BPPColor(FROMRGB(250, 240, 188));

	ColorFillVideoSurfaceArea(ButtonDestBuffer, x, y, x2, y2, usFillColorDark);
	ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2, y2, usFillColorLight);
	ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2 - 1, y2 - 1, usFillColorBack);

	usStrWidth = StringPixLength( str, uiFont );
	if( usStrWidth > w )
	{ //the string is too long, so use the wrapped method
		y += 1;
		DisplayWrappedString( x, y, w, 2, uiFont, FONT_BLACK, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		return;
	}
	//center the string vertically and horizontally.
	SetFont( uiFont );
	SetFontForeground( FONT_BLACK );
	SetFontShadow( FONT_BLACK );
	x += (w - (UINT16)StringPixLength( str, uiFont )) / 2;
	y += (h - (UINT16)GetFontHeight( uiFont)) / 2;
	mprintf( x, y, L"%s", str );
	InvalidateRegion( x, y, x2, y2 );
}

void ClickEditorButton( INT32 iEditorButtonID )
{
	GUI_BUTTON *butn;
	if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
		return;
	if ( iEditorButton[ iEditorButtonID ] != -1 )
	{
		butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
		if( butn )
			butn->uiFlags |= BUTTON_CLICKED_ON;
	}
}

void UnclickEditorButton( INT32 iEditorButtonID )
{
	GUI_BUTTON *butn;
	if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
		return;
	if ( iEditorButton[ iEditorButtonID ] != -1 )
	{
		butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
		if( butn )
			butn->uiFlags &= (~BUTTON_CLICKED_ON);
	}
}

void HideEditorButton( INT32 iEditorButtonID )
{
	HideButton( iEditorButton[ iEditorButtonID ] );
}

void ShowEditorButton( INT32 iEditorButtonID )
{
	ShowButton( iEditorButton[ iEditorButtonID ] );
}

void DisableEditorButton( INT32 iEditorButtonID )
{
	DisableButton( iEditorButton[ iEditorButtonID ] );
}

void EnableEditorButton( INT32 iEditorButtonID )
{
	EnableButton( iEditorButton[ iEditorButtonID ] );
}

void ClickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	GUI_BUTTON *b;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
	{
		Assert( iEditorButton[ i ] != -1 );
		b = ButtonList[ iEditorButton[ i ] ];
		Assert( b );
		b->uiFlags |= BUTTON_CLICKED_ON;
	}
}

void UnclickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	GUI_BUTTON *b;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
	{
		Assert( iEditorButton[ i ] != -1 );
		b = ButtonList[ iEditorButton[ i ] ];
		Assert( b );
		b->uiFlags &= (~BUTTON_CLICKED_ON);
	}
}

void HideEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
		HideButton( iEditorButton[ i ] );
}

void ShowEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
		ShowButton( iEditorButton[ i ] );
}

void DisableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
		DisableButton( iEditorButton[ i ] );
}

void EnableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
	INT32 i;
	for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
		EnableButton( iEditorButton[ i ] );
}

void RenderMapEntryPointsAndLights()
{
	INT16 sGridNo;
	INT16 sScreenX, sScreenY;
	INT32 i;
	if( gfSummaryWindowActive )
		return;
	SetFont( FONT10ARIAL );
	SetFontForeground( FONT_YELLOW );
	SetFontShadow( FONT_NEARBLACK );
	sGridNo = gMapInformation.sNorthGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"North Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	sGridNo = gMapInformation.sWestGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"West Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	sGridNo = gMapInformation.sEastGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"East Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	sGridNo = gMapInformation.sSouthGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"South Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	sGridNo = gMapInformation.sCenterGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"Center Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	sGridNo = gMapInformation.sIsolatedGridNo;
	if( sGridNo != -1 )
	{
		GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY >= -20 && sScreenY < 340 && sScreenX >= -40  && sScreenX < 640 )
		{
			DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, L"Isolated Entry Point", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		}
	}
	//Do the lights now.
	for( i = 0; i < MAX_LIGHT_SPRITES; i++ )
	{
		if( LightSprites[ i ].uiFlags & LIGHT_SPR_ACTIVE )
		{
			sGridNo = LightSprites[ i ].iY * WORLD_COLS + LightSprites[ i ].iX;
			GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
			if( sScreenY >= -50 && sScreenY < 300 && sScreenX >= -40  && sScreenX < 640 )
			{
				if( LightSprites[ i ].uiFlags & LIGHT_PRIMETIME )
					DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_ORANGE, L"Prime", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
				else if( LightSprites[ i ].uiFlags & LIGHT_NIGHTTIME )
					DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_RED, L"Night", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
				else
					DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_YELLOW, L"24Hour", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
			}
		}
	}
}

void BuildTriggerName( OBJECTTYPE *pItem, UINT16 *szItemName )
{
	if( pItem->usItem == SWITCH )
	{
		if( pItem->bFrequency == PANIC_FREQUENCY )
			swprintf( szItemName, L"Panic Trigger1" );
		else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
			swprintf( szItemName, L"Panic Trigger2" );
		else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
			swprintf( szItemName, L"Panic Trigger3" );
		else
			swprintf( szItemName, L"Trigger%d", pItem->bFrequency - 50 );
	}
	else
	{ //action item
		if( pItem->bDetonatorType == BOMB_PRESSURE )
			swprintf( szItemName, L"Pressure Action" );
		else if( pItem->bFrequency == PANIC_FREQUENCY )
			swprintf( szItemName, L"Panic Action1" );
		else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
			swprintf( szItemName, L"Panic Action2" );
		else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
			swprintf( szItemName, L"Panic Action3" );
		else
			swprintf( szItemName, L"Action%d", pItem->bFrequency - 50 );
	}
}

void RenderDoorLockInfo()
{
	INT16 i, xp, yp;
	INT16 sScreenX, sScreenY;
	UINT16 str[ 50 ];
	for( i = 0; i < gubNumDoors; i++ )
	{
		GetGridNoScreenPos( DoorTable[ i ].sGridNo, 0, &sScreenX, &sScreenY );
		if( sScreenY > 390 )
			continue;
		if( DoorTable[ i ].ubLockID != 255 )
			swprintf( str, L"%S", LockTable[ DoorTable[ i ].ubLockID ].ubEditorName );
		else
			swprintf( str, L"No Lock ID" );
		xp = sScreenX - 10;
		yp = sScreenY - 40;
		DisplayWrappedString( xp, yp, 60, 2, FONT10ARIAL, FONT_LTKHAKI, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
		if( DoorTable[ i ].ubTrapID )
		{
			SetFont( FONT10ARIAL );
			SetFontForeground( FONT_RED );
			SetFontShadow( FONT_NEARBLACK );
			switch( DoorTable[ i ].ubTrapID )
			{
				case EXPLOSION:
					swprintf( str, L"Explosion Trap" );
					break;
				case ELECTRIC:
					swprintf( str, L"Electric Trap" );
					break;
				case SIREN:
					swprintf( str, L"Siren Trap" );
					break;
				case SILENT_ALARM:
					swprintf( str, L"Silent Alarm" );
					break;
				case SUPER_ELECTRIC:
					swprintf( str, L"Super Electric Trap" );
					break;

			}
			xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
			yp = sScreenY;
			mprintf( xp, yp, str );
			swprintf( str, L"Trap Level %d", DoorTable[ i ].ubTrapLevel );
			xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
			mprintf( xp, yp+10, str );
		}
	}
}

void RenderSelectedItemBlownUp()
{
	UINT32 uiVideoObjectIndex;
	HVOBJECT hVObject;
	INT16 sScreenX, sScreenY, xp, yp;
	ITEM_POOL	*pItemPool;
	UINT16 szItemName[ SIZE_ITEM_NAME ];
	INT32 i;
	INT16 sWidth, sHeight, sOffsetX, sOffsetY;

	GetGridNoScreenPos( gsItemGridNo, 0, &sScreenX, &sScreenY );

	if( sScreenY > 340 )
		return;

	//Display the enlarged item graphic
	uiVideoObjectIndex = GetInterfaceGraphicForItem( &Item[ gpItem->usItem ] );
	GetVideoObject( &hVObject, uiVideoObjectIndex );
	
	sWidth = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usWidth;
	sOffsetX = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetX;
	xp = sScreenX + (40 - sWidth - sOffsetX*2) / 2;
	
	sHeight = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usHeight;
	sOffsetY = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetY;
	yp = sScreenY + (20 - sHeight - sOffsetY*2) / 2;

	BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, Item[ gpItem->usItem ].ubGraphicNum, xp, yp, Get16BPPColor(FROMRGB(0, 140, 170)), TRUE );

	//Display the item name above it
	SetFont( FONT10ARIAL );
	SetFontForeground( FONT_YELLOW );
	SetFontShadow( FONT_NEARBLACK );
	if( gpItem->usItem == ACTION_ITEM || gpItem->usItem == SWITCH )
	{
		BuildTriggerName( gpItem, szItemName );
	}
	else if( Item[ gpItem->usItem ].usItemClass == IC_KEY )
	{
		swprintf( szItemName, L"%S", LockTable[ gpItem->ubKeyID ].ubEditorName );
	}
	else
	{
		LoadItemInfo( gpItem->usItem, szItemName, NULL );
	}
	xp = sScreenX - (StringPixLength( szItemName, FONT10ARIAL ) - 40) / 2;
	yp -= 10;
	mprintf( xp, yp, szItemName );

	if( gpItem->usItem == ACTION_ITEM )
	{
		UINT16 *pStr;
		pStr = GetActionItemName( gpItem );
		xp = sScreenX - (StringPixLength( pStr, FONT10ARIALBOLD ) - 40) / 2;
		yp += 10;
		SetFont( FONT10ARIALBOLD );
		SetFontForeground( FONT_LTKHAKI );
		mprintf( xp, yp, pStr );
		SetFontForeground( FONT_YELLOW );
	}

	//Count the number of items in the current pool, and display that.
	i = 0;
	GetItemPool( gsItemGridNo, &pItemPool, 0 );
	Assert( pItemPool );
	while( pItemPool )
	{
		i++;
		pItemPool = pItemPool->pNext;
	}
	xp = sScreenX;
	yp = sScreenY + 10;
	mprintf( xp, yp, L"%d", i );
	
	//If the item is hidden, render a blinking H (just like DG)
	if( gWorldItems[ gpItemPool->iItemIndex ].bVisible == HIDDEN_ITEM || 
			gWorldItems[ gpItemPool->iItemIndex ].bVisible == BURIED )
	{
		SetFont( FONT10ARIALBOLD );
		if( GetJA2Clock() % 1000 > 500 )
		{
			SetFontForeground( 249 );
		}
		mprintf( sScreenX + 16, sScreenY + 7, L"H" );
		InvalidateRegion( sScreenX + 16, sScreenY + 7, sScreenX + 24, sScreenY + 27 );
	}
}

void RenderEditorInfo( )
{
	wchar_t					FPSText[ 50 ];
	static INT32		iSpewWarning = 0;
	INT16						iMapIndex;

	SetFont( FONT12POINT1 );
	SetFontForeground( FONT_BLACK );
	SetFontBackground( FONT_BLACK );

	//Display the mapindex position
	if( GetMouseMapPos( &iMapIndex ) )
		swprintf( FPSText, L"   (%d)   ", iMapIndex );
	else
		swprintf( FPSText, L"          " );
	mprintfEditor( (UINT16)(50-StringPixLength( FPSText, FONT12POINT1 )/2), 463, FPSText );

	switch( iCurrentTaskbar )
	{
		case TASK_OPTIONS:
			if( !gfWorldLoaded || giCurrentTilesetID < 0 )
				mprintf( 260, 445, L"No map currently loaded." );
			else
				mprintf( 260, 445, L"File:  %S, Current Tileset:  %s", 
					gubFilename, gTilesets[ giCurrentTilesetID ].zName );
			break;
		case TASK_TERRAIN:
			if( gusSelectionType == LINESELECTION )
				swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
			DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, 220, 430, 60, 30 );
			swprintf( FPSText, L"%d%%", gusSelectionDensity );
			DrawEditorInfoBox( FPSText, FONT12POINT1, 310, 430, 40, 30 );
			break;
		case TASK_ITEMS:
			RenderEditorItemsInfo();
			UpdateItemStatsPanel();
			break;
		case TASK_BUILDINGS:
			UpdateBuildingsInfo();
			if( gusSelectionType == LINESELECTION )
				swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
			DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, 530, 430, 60, 30 );
			break;
		case TASK_MERCS:
			UpdateMercsInfo();
			break;
		case TASK_MAPINFO:
			UpdateMapInfo();
			if( gusSelectionType == LINESELECTION )
				swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
			DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, 440, 430, 60, 30 );
			break;
	}
}

//This is in ButtonSystem.c as a hack.  Because we need to save the buffer whenever we do a full
//taskbar render, we need to draw the buttons without hilites, hence this flag.  This flag is
//always true in ButtonSystem.c, so it won't effect anything else.
extern BOOLEAN gfGotoGridNoUI;

void ProcessEditorRendering()
{
	BOOLEAN fSaveBuffer = FALSE;
	if( gfRenderTaskbar ) //do a full taskbar render.
	{
		ClearTaskbarRegion( 0, 360, 640, 480 );
		RenderTerrainTileButtons();
		MarkButtonsDirty();
		gfRenderTaskbar = FALSE;
		fSaveBuffer = TRUE;
		gfRenderDrawingMode = TRUE;
		gfRenderHilights = FALSE;
		gfRenderMercInfo = TRUE;
	}
	if( gfRenderDrawingMode )
	{
	  if( iCurrentTaskbar == TASK_BUILDINGS || iCurrentTaskbar == TASK_TERRAIN || iCurrentTaskbar == TASK_ITEMS ) 
		{
			ShowCurrentDrawingMode();
			gfRenderDrawingMode = FALSE;
		}
	}
	//render dynamically changed buttons only  
	RenderButtons( );

	if( gfSummaryWindowActive )
		RenderSummaryWindow();
	else if( !gfGotoGridNoUI && !InOverheadMap() )
		RenderMercStrings();

	if( gfEditingDoor )
		RenderDoorEditingWindow();

	if( TextInputMode() )
		RenderAllTextFields();
	RenderEditorInfo();

	if( !gfSummaryWindowActive && !gfGotoGridNoUI && !InOverheadMap() )
	{
		if( gpItem && gsItemGridNo != -1 )
			RenderSelectedItemBlownUp();
		if( iCurrentTaskbar == TASK_MAPINFO )
			RenderMapEntryPointsAndLights();
		if( iDrawMode == DRAW_MODE_PLACE_ITEM && eInfo.uiItemType == TBAR_MODE_ITEM_KEYS || 
			  iDrawMode == DRAW_MODE_DOORKEYS )
			RenderDoorLockInfo();
	}



	if( fSaveBuffer )
		BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 360, 640, 120 );

	//Make sure this is TRUE at all times.
	//It is set to false when before we save the buffer, so the buttons don't get 
	//rendered with hilites, in case the mouse is over one.  
	gfRenderHilights = TRUE;

	RenderButtonsFastHelp();

}


#endif