//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
// software: you can redistribute it and/or modify it under the terms of 
// the GNU General Public License as published by the Free Software Foundation, 
// either version 3 of the License, or (at your option) any later version.

// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
// in the hope that it will be useful, but with permitted additional restrictions 
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
// distributed with this program. You should have received a copy of the 
// GNU General Public License along with permitted additional restrictions 
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection

/* $Header: /CounterStrike/MAPEDIT.CPP 2     3/13/97 2:05p Steve_tall $ */
/***************************************************************************
 **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **
 ***************************************************************************
 *                                                                         *
 *                 Project Name : Command & Conquer                        *
 *                                                                         *
 *                    File Name : MAPEDIT.CPP                              *
 *                                                                         *
 *                   Programmer : Bill Randolph                            *
 *                                                                         *
 *                   Start Date : October 20, 1994                         *
 *                                                                         *
 *                  Last Update : February 2, 1995   [BR]                  *
 *                                                                         *
 *-------------------------------------------------------------------------*
 *   Map Editor overloaded routines & utility routines                     *
 *-------------------------------------------------------------------------*
 * Map Editor modules:                                                     *
 * (Yes, they're all one huge class.)                                      *
 *      mapedit.cpp:   overloaded routines, utility routines               *
 *      mapeddlg.cpp:   map editor dialogs, most of the main menu options  *
 *      mapedplc.cpp:   object-placing routines                            *
 *      mapedsel.cpp:   object-selection & manipulation routines           *
 *      mapedtm.cpp:   team-editing routines                               *
 *-------------------------------------------------------------------------*
 * Functions:                                                              *
 *   MapEditClass::AI -- The map editor's main logic                       *
 *   MapEditClass::Read_INI -- overloaded Read_INI function                *
 *   MapEditClass::AI_Menu -- menu of AI options                           *
 *   MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list  *
 *   MapEditClass::Clear_List -- clears the internal chooseable object list*
 *   MapEditClass::Cycle_House -- finds next valid house for object type   *
 *   MapEditClass::Draw_It -- overloaded Redraw routine                    *
 *   MapEditClass::Fatal -- exits with error message                       *
 *   MapEditClass::Main_Menu -- main menu processor for map editor         *
 *   MapEditClass::MapEditClass -- class constructor                       *
 *   MapEditClass::Mouse_Moved -- checks for mouse motion                  *
 *   MapEditClass::One_Time -- one-time initialization                     *
 *   MapEditClass::Verify_House -- sees if given house can own given obj   *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include	"function.h"

#ifdef SCENARIO_EDITOR

/*
**	Array of all missions supported by the map editor
*/
MissionType MapEditClass::MapEditMissions[] = {
	MISSION_GUARD,
	MISSION_STICKY,
	MISSION_HARMLESS,
	MISSION_HARVEST,
	MISSION_GUARD_AREA,
	MISSION_RETURN,
	MISSION_AMBUSH,
	MISSION_HUNT,
	MISSION_SLEEP,
};
#define NUM_EDIT_MISSIONS (sizeof(MapEditClass::MapEditMissions) / sizeof(MapEditClass::MapEditMissions[0]))


/*
**	For menu processing
*/
extern int UnknownKey;					// in menus.cpp

char MapEditClass::HealthBuf[20];


/***************************************************************************
 * MapEditClass::MapEditClass -- class constructor                         *
 *                                                                         *
 * INPUT:                                                                  *
 *      none.                                                              *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   10/20/1994 BR : Created.                                              *
 *=========================================================================*/
MapEditClass::MapEditClass(void)
{
	/*
	**	Init data members.
	*/
//	ScenVar = SCEN_VAR_A;
	ObjCount = 0;
	LastChoice = 0;
	LastHouse = HOUSE_GOOD;
	GrabbedObject = 0;
	for (int i=0; i < NUM_EDIT_CLASSES; i++) {
		NumType[i] = 0;
		TypeOffset[i] = 0;
	}
	Scen.Waypoint[WAYPT_HOME] = 0;
	CurrentCell = 0;
	CurTeam = NULL;
	CurTrigger = NULL;
	Changed = 0;
	LMouseDown = 0;
	BaseBuilding = false;
//	BasePercent = 100;
}


/***************************************************************************
 * MapEditClass::One_Time -- one-time initialization                       *
 *                                                                         *
 * INPUT:                                                                  *
 *      none.                                                              *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   02/02/1995 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::One_Time(void)
{
	MouseClass::One_Time();

	/*
	**	The map: a single large "button"
	*/
#ifdef WIN32
	MapArea = new ControlClass(MAP_AREA, 0, 8, 640-8, 400-8, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);
#else
	MapArea = new ControlClass(MAP_AREA, 0, 8, 312, 192, GadgetClass::LEFTPRESS | GadgetClass::LEFTRELEASE, false);
#endif

	/*
	**	House buttons
	*/
	HouseList = new ListClass(POPUP_HOUSELIST, POPUP_HOUSE_X, POPUP_HOUSE_Y, POPUP_HOUSE_W, POPUP_HOUSE_H,
		TPF_EFNT|TPF_NOSHADOW,
		MFCD::Retrieve("EBTN-UP.SHP"),
		MFCD::Retrieve("EBTN-DN.SHP"));
	for (HousesType house = HOUSE_FIRST; house < HOUSE_COUNT; house++) {
		HouseList->Add_Item(HouseTypeClass::As_Reference(house).IniName);
	}

	/*
	**	The mission list box
	*/
	MissionList = new ListClass(POPUP_MISSIONLIST,
		POPUP_MISSION_X, POPUP_MISSION_Y, POPUP_MISSION_W, POPUP_MISSION_H,
		TPF_EFNT|TPF_NOSHADOW,
		MFCD::Retrieve("EBTN-UP.SHP"),
		MFCD::Retrieve("EBTN-DN.SHP"));

	for (int i = 0; i < NUM_EDIT_MISSIONS; i++) {
		MissionList->Add_Item(MissionClass::Mission_Name(MapEditMissions[i]));
	}

	/*
	**	The health bar
	*/
	HealthGauge = new TriColorGaugeClass(POPUP_HEALTHGAUGE,
		POPUP_HEALTH_X, POPUP_HEALTH_Y, POPUP_HEALTH_W, POPUP_HEALTH_H);
	HealthGauge->Use_Thumb(true);
	HealthGauge->Set_Maximum(0x100);
	HealthGauge->Set_Red_Limit(0x3f - 1);
	HealthGauge->Set_Yellow_Limit(0x7f - 1);

	/*
	**	The health text label
	*/
	HealthBuf[0] = 0;
	HealthText = new TextLabelClass(HealthBuf,
		POPUP_HEALTH_X + POPUP_HEALTH_W / 2,
		POPUP_HEALTH_Y + POPUP_HEALTH_H + 1,
		GadgetClass::Get_Color_Scheme(),
		TPF_CENTER | TPF_FULLSHADOW | TPF_EFNT);

	/*
	**	Building attribute buttons.
	*/
	Sellable = new TextButtonClass(POPUP_SELLABLE, TXT_SELLABLE, TPF_EBUTTON, 320-65, 200-25, 60);
	Rebuildable = new TextButtonClass(POPUP_REBUILDABLE, TXT_REBUILD, TPF_EBUTTON, 320-65, 200-15, 60);

	/*
	**	The facing dial
	*/
	FacingDial = new Dial8Class(POPUP_FACINGDIAL, POPUP_FACEBOX_X,
		POPUP_FACEBOX_Y, POPUP_FACEBOX_W, POPUP_FACEBOX_H, (DirType)0);

	/*
	**	The base percent-built slider & its label
	*/
	BaseGauge = new GaugeClass(POPUP_BASEPERCENT, POPUP_BASE_X, POPUP_BASE_Y, POPUP_BASE_W, POPUP_BASE_H);
	BaseLabel = new TextLabelClass ("Base:", POPUP_BASE_X - 3, POPUP_BASE_Y, GadgetClass::Get_Color_Scheme(),
		TPF_RIGHT | TPF_NOSHADOW | TPF_EFNT);
	BaseGauge->Set_Maximum(100);
	BaseGauge->Set_Value(Scen.Percent);
}


/***********************************************************************************************
 * MapeditClass::Init_IO -- Reinitializes the radar map at scenario start.                     *
 *                                                                                             *
 * INPUT:   none                                                                               *
 *                                                                                             *
 * OUTPUT:  none                                                                               *
 *                                                                                             *
 * WARNINGS:   none                                                                            *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   12/22/1994 JLB : Created.                                                                 *
 *=============================================================================================*/
void MapEditClass::Init_IO(void)
{
	/*
	**	For normal game mode, jump to the parent's Init routine.
	*/
	if (!Debug_Map) {

		MouseClass::Init_IO();

	} else {

		/*
		**	For editor mode, add the map area to the button input list
		*/
		Buttons = 0;
		Add_A_Button(*BaseGauge);
		Add_A_Button(*BaseLabel);
		Add_A_Button(*MapArea);
	}
}


/***************************************************************************
 * MapEditClass::Clear_List -- clears the internal chooseable object list   *
 *                                                                         *
 * INPUT:                                                                  *
 *      none.                                                              *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   10/20/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::Clear_List(void)
{
	/*
	**	Set # object type ptrs to 0, set NumType for each type to 0
	*/
	ObjCount = 0;
	for (int i = 0; i < NUM_EDIT_CLASSES; i++) {
		NumType[i] = 0;
	}
}


/***************************************************************************
 * MapEditClass::Add_To_List -- adds a TypeClass to the chooseable list     *
 *                                                                         *
 * Use this routine to add an object to the game object selection list.    *
 * This list is used by the Add_Object function. All items located in the  *
 * list will appear and be chooseable by that function. Make sure to       *
 * clear the list before adding a sequence of items to it. Clearing        *
 * the list is accomplished by the Clear_List() function.                  *
 *                                                                         *
 * INPUT:                                                                  *
 *      object      ptr to ObjectTypeClass to add                          *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      bool: was the object added to the list?  A failure could occur if  *
 *      NULL were passed in or the list is full.                           *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   06/04/1994 JLB : Created.                                             *
 *=========================================================================*/
bool MapEditClass::Add_To_List(ObjectTypeClass const * object)
{
	/*
	**	Add the object if there's room.
	*/
	if (object && ObjCount < MAX_EDIT_OBJECTS) {
		Objects[ObjCount++] = object;

		/*
		**	Update type counters.
		*/
		switch (object->What_Am_I()) {
			case RTTI_TEMPLATETYPE:
				NumType[0]++;
				break;

			case RTTI_OVERLAYTYPE:
				NumType[1]++;
				break;

			case RTTI_SMUDGETYPE:
				NumType[2]++;
				break;

			case RTTI_TERRAINTYPE:
				NumType[3]++;
				break;

			case RTTI_UNITTYPE:
				NumType[4]++;
				break;

			case RTTI_INFANTRYTYPE:
				NumType[5]++;
				break;

			case RTTI_VESSELTYPE:
				NumType[6]++;
				break;

			case RTTI_BUILDINGTYPE:
				NumType[7]++;
				break;

			case RTTI_AIRCRAFTTYPE:
				NumType[8]++;
				break;
		}
		return(true);
	}

	return(false);
}


/***************************************************************************
 * MapEditClass::AI -- The map editor's main logic                         *
 *                                                                         *
 * This routine overloads the parent's (DisplayClass) AI function.         *
 * It checks for any input specific to map editing, and calls the parent   *
 * AI routine to handle scrolling and other mainstream map stuff.          *
 *                                                                         *
 * If this detects one of its special input keys, it sets 'input' to 0     *
 * before calling the parent AI routine; this prevents input conflict.     *
 *                                                                         *
 * SUPPORTED INPUT:                                                        *
 * General:                                                                *
 *      F2/RMOUSE:            main menu                                    *
 *      F6:                  toggles show-passable mode                    *
 *      HOME:                  go to the Home Cell (scenario's start position)*
 *      SHIFT-HOME:            set the Home Cell to the current TacticalCell*
 *      ESC:                  exits to DOS                                 *
 * Object Placement:                                                       *
 *      INSERT:               go into placement mode                       *
 *      ESC:                  exit placement mode                          *
 *      LEFT/RIGHT:          prev/next placement object                    *
 *      PGUP/PGDN:            prev/next placement category                 *
 *      HOME:                  1st placement object (clear template)       *
 *      h/H:                  toggle house of placement object             *
 *      LMOUSE:               place the placement object                   *
 *      MOUSE MOTION:         "paint" with the placement object            *
 * Object selection:                                                       *
 *      LMOUSE:               select & "grab" current object               *
 *                           If no object is present where the mouse is    *
 *                           clicked, the current object is de-selected    *
 *                           If the same object is clicked on, it stays    *
 *                           selected. Also displays the object-editing    *
 *                           gadgets.                                      *
 *      LMOUSE RLSE:         release currently-grabbed object              *
 *      MOUSE MOTION:         if an object is grabbed, moves the object    *
 *      SHIFT|ALT|ARROW:      moves object in that direction               *
 *      DELETE               deletes currently-selected object             *
 * Object-editing controls:                                                *
 *      POPUP_GDI:            makes GDI the owner of this object           *
 *      POPUP_NOD:            makes NOD the owner of this object           *
 *      POPUP_MISSIONLIST:   sets that mission for this object             *
 *      POPUP_HEALTHGAUGE:   sets that health value for this object        *
 *      POPUP_FACINGDIAL:      sets the object's facing                    *
 *                                                                         *
 * Changed is set when you:                                                *
 *      - place an object                                                  *
 *      - move a grabbed object                                            *
 *      - delete an object                                                 *
 *      - size the map                                                     *
 *      - create a new scenario                                            *
 *   Changed is cleared when you:                                          *
 *      - Save the scenario                                                *
 *      - Load a scenario                                                  *
 *      - Play the scenario                                                *
 *                                                                         *
 * INPUT:                                                                  *
 *      input      KN_ value, 0 if none                                    *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   10/20/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::AI(KeyNumType & input, int x, int y)
{
	int rc;
	MissionType mission;
	int strength;
	CELL cell;
	int i;
	int found;									// for removing a waypoint label
	int waypt_idx;								// for labelling a waypoint
	BaseNodeClass * node;						// for removing from an AI Base
	HousesType house;
	char wayname[4];

	/*
	**	Trap 'F2' regardless of whether we're in game or editor mode
	*/
	if (Debug_Flag) {
		if ((input == KN_F2 && Session.Type == GAME_NORMAL) || input == (KN_F2 | KN_CTRL_BIT)) {
			ScenarioInit = 0;

			/*
			** If we're in editor mode & Changed is set, prompt for saving changes
			*/
			if (Debug_Map && Changed) {
				rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
				HidPage.Clear();
				Flag_To_Redraw(true);
				Render();

				/*
				**	User wants to save
				*/
				if (rc == 0) {

					/*
					**	If save cancelled, abort game
					*/
					if (Save_Scenario()!=0) {
						input = KN_NONE;
					} else {
						Changed = 0;
						Go_Editor(!Debug_Map);
					}
				} else {

					/*
					**	User doesn't want to save
					*/
					Go_Editor(!Debug_Map);
				}
			} else {
				/*
				** If we're in game mode, set Changed to 0 (so if we didn't save our
				** changes above, they won't keep coming back to haunt us with continual
				** Save Changes? prompts!)
				*/
				if (!Debug_Map) {
					Changed = 0;
				}
				BaseGauge->Set_Value(Scen.Percent);
				Go_Editor(!Debug_Map);
			}
		}
	}

	/*
	**	For normal game mode, jump to the parent's AI routine.
	*/
	if (!Debug_Map) {
		MouseClass::AI(input, x, y);
		return;
	}

	::Frame++;

	/*
	**	Do special mouse processing if the mouse is over the map
	*/
	if (Get_Mouse_X() > TacPixelX && Get_Mouse_X() <
		TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
		Get_Mouse_Y() > TacPixelY && Get_Mouse_Y() <
		TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {

		/*
		**	When the mouse moves over a scrolling edge, ScrollClass changes its
		**	shape to the appropriate arrow or NO symbol; it's our job to change it
		**	back to normal (or whatever the shape is set to by Set_Default_Mouse())
		**	when it re-enters the map area.
		*/
		if (CurTrigger) {
			Override_Mouse_Shape(MOUSE_CAN_MOVE);
		} else {
			Override_Mouse_Shape(MOUSE_NORMAL);
		}
	}

	/*
	**	Set 'ZoneCell' to track the mouse cursor around over the map.  Do this
	**	even if the map is scrolling.
	*/
	if (Get_Mouse_X() >= TacPixelX && Get_Mouse_X() <=
		TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
		Get_Mouse_Y() >= TacPixelY && Get_Mouse_Y() <=
		TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {

		cell = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());
		if (cell != -1) {
			Set_Cursor_Pos(cell);
			if (PendingObject) {
				Flag_To_Redraw(true);
			}
		}
	}

	/*
	**	Check for mouse motion while left button is down.
	*/
	rc = Mouse_Moved();
	if (LMouseDown && rc) {

		/*
		**	"Paint" mode: place current object, and restart placement
		*/
		if (PendingObject) {
			Flag_To_Redraw(true);
			if (Place_Object() == 0) {
				Changed = 1;
				Start_Placement();
			}
		} else {

			/*
			**	Move the currently-grabbed object
			*/
			if (GrabbedObject) {
				GrabbedObject->Mark(MARK_CHANGE);
				if (Move_Grabbed_Object() == 0) {
					Changed = 1;
				}
			}
		}
	}

	/*
	**	Trap special editing keys; if one is detected, set 'input' to 0 to
	**	prevent a conflict with parent's AI().
	*/
	switch (input) {
		/*
		** F2/RMOUSE = pop up main menu
		*/
		case KN_RMOUSE:

			/*
			**	Turn off placement mode
			*/
			if (PendingObject) {
				if (BaseBuilding) {
					Cancel_Base_Building();
				} else {
					Cancel_Placement();
				}
			}

			/*
			**	Turn off trigger placement mode
			*/
			if (CurTrigger) {
				Stop_Trigger_Placement();
			}

			/*
			**	Unselect object & hide popup controls
			*/
			if (CurrentObject.Count()) {
				CurrentObject[0]->Unselect();
				Popup_Controls();
			}
			Main_Menu();
			input = KN_NONE;
			break;

		/*
		**	F6 = toggle passable/impassable display
		*/
		case KN_F6:
			Debug_Passable = (Debug_Passable == false);
			HidPage.Clear();
			Flag_To_Redraw(true);
			input = KN_NONE;
			break;

		/*
		**	INSERT = go into object-placement mode
		*/
		case KN_INSERT:
			if (!PendingObject) {
				/*
				**	Unselect current object, hide popup controls
				*/
				if (CurrentObject.Count()) {
					CurrentObject[0]->Unselect();
					Popup_Controls();
				}

				/*
				**	Go into placement mode
				*/
				Start_Placement();
			}
			input = KN_NONE;
			break;

		/*
		**	ESC = exit placement mode, or exit to DOS
		*/
		case KN_ESC:

			/*
			**	Exit object placement mode
			*/
			if (PendingObject) {
				if (BaseBuilding) {
					Cancel_Base_Building();
				} else {
					Cancel_Placement();
				}
				input = KN_NONE;
				break;
			} else {

				/*
				**	Exit trigger placement mode
				*/
				if (CurTrigger) {
					Stop_Trigger_Placement();
					input = KN_NONE;
					break;
				} else {
					rc = WWMessageBox().Process("Exit Scenario Editor?", TXT_YES, TXT_NO);
					HidPage.Clear();
					Flag_To_Redraw(true);
					Render();

					/*
					**	User doesn't want to exit; return to editor
					*/
					if (rc==1) {
						input = KN_NONE;
						break;
					}

					/*
					**	If changed, prompt for saving
					*/
					if (Changed) {
						rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
						HidPage.Clear();
						Flag_To_Redraw(true);
						Render();

						/*
						**	User wants to save
						*/
						if (rc == 0) {

							/*
							**	If save cancelled, abort exit
							*/
							if (Save_Scenario()!=0) {
								input = KN_NONE;
								break;
							} else {
								Changed = 0;
							}
						}
					}
				}
			}
			//Prog_End();
			Emergency_Exit(0);
			break;

		/*
		**	LEFT = go to previous placement object
		*/
		case KN_LEFT:
			if (PendingObject) {
				Place_Prev();
			}
			input = KN_NONE;
			break;

		/*
		**	RIGHT = go to next placement object
		*/
		case KN_RIGHT:
			if (PendingObject) {
				Place_Next();
			}
			input = KN_NONE;
			break;

		/*
		**	PGUP = go to previous placement category
		*/
		case KN_PGUP:
			if (PendingObject) {
				Place_Prev_Category();
			}
			input = KN_NONE;
			break;

		/*
		**	PGDN = go to next placement category
		*/
		case KN_PGDN:
			if (PendingObject) {
				Place_Next_Category();
			}
			input = KN_NONE;
			break;

		/*
		**	HOME = jump to first placement object, or go to Home Cell
		*/
		case KN_HOME:
			if (PendingObject) {
				Place_Home();
			} else {

				/*
				**	Set map position
				*/
				ScenarioInit++;
				Set_Tactical_Position(Scen.Waypoint[WAYPT_HOME]);
				ScenarioInit--;

				/*
				**	Force map to redraw
				*/
				HidPage.Clear();
				Flag_To_Redraw(true);
				Render();
			}
			input = KN_NONE;
			break;

		/*
		**	SHIFT-HOME: set new Home Cell position
		*/
		case ((int)KN_HOME | (int)KN_SHIFT_BIT):
			if (CurrentCell != 0) {

			/*
			** Unflag the old Home Cell, if there are no other waypoints
			** pointing to it
			*/
			cell = Scen.Waypoint[WAYPT_HOME];

			if (cell != -1) {
				found = 0;
				for (i = 0; i < WAYPT_COUNT; i++) {
					if (i != WAYPT_HOME && Scen.Waypoint[i]==cell) {
						found = 1;
					}
				}

				if (found==0) {
					(*this)[cell].IsWaypoint = 0;
					Flag_Cell(cell);
				}

			}

			/*
			** Now set the new Home cell
			*/
//			Scen.Waypoint[WAYPT_HOME] = Coord_Cell(TacticalCoord);
//			(*this)[TacticalCoord].IsWaypoint = 1;
//			Flag_Cell(Coord_Cell(TacticalCoord));
			Scen.Waypoint[WAYPT_HOME] = CurrentCell;
			(*this)[CurrentCell].IsWaypoint = 1;
			Flag_Cell(CurrentCell);

			Changed = 1;
			input = KN_NONE;
}
			break;

		/*
		**	SHIFT-R: set new Reinforcement Cell position.  Don't allow setting
		**	the Reinf. Cell to the same as the Home Cell (for display purposes.)
		*/
		case ((int)KN_R | (int)KN_SHIFT_BIT):
			if (CurrentCell==0 || CurrentCell==Scen.Waypoint[WAYPT_HOME]) {
				break;
			}

			/*
			** Unflag the old Reinforcement Cell, if there are no other waypoints
			** pointing to it
			*/
			cell = Scen.Waypoint[WAYPT_REINF];

			if (cell != -1) {
				found = 0;
				for (i = 0; i < WAYPT_COUNT; i++) {
					if (i != WAYPT_REINF && Scen.Waypoint[i]==cell) {
						found = 1;
					}
				}

				if (found==0) {
					(*this)[cell].IsWaypoint = 0;
					Flag_Cell(cell);
				}

			}
			/*
			** Now set the new Reinforcement cell
			*/
			Scen.Waypoint[WAYPT_REINF] = CurrentCell;
			(*this)[CurrentCell].IsWaypoint = 1;
			Flag_Cell(CurrentCell);
			Changed = 1;
			input = KN_NONE;
			break;

		/*
		**	ALT-Letter: Label a waypoint cell
		*/
		case ((int)KN_A | (int)KN_ALT_BIT):
		case ((int)KN_B | (int)KN_ALT_BIT):
		case ((int)KN_C | (int)KN_ALT_BIT):
		case ((int)KN_D | (int)KN_ALT_BIT):
		case ((int)KN_E | (int)KN_ALT_BIT):
		case ((int)KN_F | (int)KN_ALT_BIT):
		case ((int)KN_G | (int)KN_ALT_BIT):
		case ((int)KN_H | (int)KN_ALT_BIT):
		case ((int)KN_I | (int)KN_ALT_BIT):
		case ((int)KN_J | (int)KN_ALT_BIT):
		case ((int)KN_K | (int)KN_ALT_BIT):
		case ((int)KN_L | (int)KN_ALT_BIT):
		case ((int)KN_M | (int)KN_ALT_BIT):
		case ((int)KN_N | (int)KN_ALT_BIT):
		case ((int)KN_O | (int)KN_ALT_BIT):
		case ((int)KN_P | (int)KN_ALT_BIT):
		case ((int)KN_Q | (int)KN_ALT_BIT):
		case ((int)KN_R | (int)KN_ALT_BIT):
		case ((int)KN_S | (int)KN_ALT_BIT):
		case ((int)KN_T | (int)KN_ALT_BIT):
		case ((int)KN_U | (int)KN_ALT_BIT):
		case ((int)KN_V | (int)KN_ALT_BIT):
		case ((int)KN_W | (int)KN_ALT_BIT):
		case ((int)KN_X | (int)KN_ALT_BIT):
		case ((int)KN_Y | (int)KN_ALT_BIT):
		case ((int)KN_Z | (int)KN_ALT_BIT):
			if (CurrentCell != 0) {
#ifdef WIN32
				waypt_idx = (input & ~KN_ALT_BIT) - KN_A;
#else
				waypt_idx = KN_To_KA(input & 0x00ff) - KA_a;
#endif
				Update_Waypoint(waypt_idx);
			}
			input = KN_NONE;
			break;

		/*
		** ALT-. : Designate an extended (2-letter) waypoint name
		*/
		case KN_PERIOD:
		case ((int)KN_PERIOD | (int)KN_ALT_BIT):
			if (CurrentCell != 0 && Get_Waypoint_Name(wayname)) {
				int waynm = 0;
				if (strlen(wayname)) {
					wayname[0] = toupper(wayname[0]);
					wayname[1] = toupper(wayname[1]);
					if (wayname[0] >= 'A' && wayname[0] <= 'Z') {
						waynm = wayname[0] - 'A';
						if (wayname[1] >= 'A' && wayname[1] <= 'Z') {
							waynm = (waynm+1)*26 + (wayname[1] - 'A');
						}
						if (waynm < WAYPT_HOME) Update_Waypoint(waynm);
					}
				}
			}
			input = KN_NONE;
			break;

#ifdef OBSOLETE
		/*
		**	ALT-1-4: Designate a cell as a capture-the-flag cell.
		*/
		case ((int)KN_1 | (int)KN_ALT_BIT):
		case ((int)KN_2 | (int)KN_ALT_BIT):
		case ((int)KN_3 | (int)KN_ALT_BIT):
		case ((int)KN_4 | (int)KN_ALT_BIT):

			/*
			**	If there's a current cell, place the flag & waypoint there.
			*/
			if (CurrentCell != 0) {
				waypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);
//				waypt_idx = (KN_To_KA(input & 0xff) - KA_1);
				house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
				if (HouseClass::As_Pointer(house)) {
					HouseClass::As_Pointer(house)->Flag_Attach(CurrentCell, true);
				}
			} else {

				/*
				**	If there's a current object, attach the flag to it and clear the
				**	waypoint.
				*/
				if (CurrentObject[0] != 0) {
					waypt_idx = (Keyboard->To_ASCII((KeyNumType)(input & 0xff)) - KA_1);
					house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
					if (HouseClass::As_Pointer(house) && CurrentObject[0]->What_Am_I() == RTTI_UNIT) {
						HouseClass::As_Pointer(house)->Flag_Attach((UnitClass *)CurrentObject[0], true);
					}
				}
			}
			input = KN_NONE;
			break;
#endif

		/*
		**	ALT-Space: Remove a waypoint designation
		*/
		case ((int)KN_SPACE | (int)KN_ALT_BIT):
			if (CurrentCell != 0) {

				/*
				**	Loop through letter waypoints; if this cell is one of them,
				**	clear that waypoint.
				*/
				for (i = 0 ; i < WAYPT_HOME; i++) {
					if (Scen.Waypoint[i]==CurrentCell)
						Scen.Waypoint[i] = -1;
				}

				/*
				**	Loop through flag home values; if this cell is one of them, clear
				**	that waypoint.
				*/
				for (i = 0; i < MAX_PLAYERS; i++) {
					house = (HousesType)(HOUSE_MULTI1 + i);
					if (HouseClass::As_Pointer(house) &&
						CurrentCell == HouseClass::As_Pointer(house)->FlagHome)
					HouseClass::As_Pointer(house)->Flag_Remove(As_Target(CurrentCell), true);
				}

				/*
				**	If there are no more waypoints on this cell, clear the cell's
				**	waypoint designation.
				*/
				if (Scen.Waypoint[WAYPT_HOME]!=CurrentCell &&
					Scen.Waypoint[WAYPT_REINF]!=CurrentCell)
					(*this)[CurrentCell].IsWaypoint = 0;
				Changed = 1;
				Flag_Cell(CurrentCell);
			}
			input = KN_NONE;
			break;

		/*
		**	'H' = toggle current placement object's house
		*/
		case KN_H:
		case ((int)KN_H | (int)KN_SHIFT_BIT):
			if (PendingObject) {
				Toggle_House();
			}
			input = KN_NONE;
			break;

		/*
		**	Left-mouse click:
		**	Button DOWN:
		**	- Toggle LMouseDown
		**	- If we're in placement mode, try to place the current object
		**	- If success, re-enter placement mode
		**	- Otherwise, try to select an object, and "grab" it if there is one
		**	- If no object, then select that cell as the "current" cell
		**	Button UP:
		**	- Toggle LMouseDown
		**	- release any grabbed object
		*/
		case ((int)MAP_AREA | (int)KN_BUTTON):

			/*
			**	Left Button DOWN
			*/
			if (Keyboard->Down(KN_LMOUSE)) {
				LMouseDown = 1;

				/*
				**	Placement mode: place an object
				*/
				if (PendingObject) {
					if (Place_Object()==0) {
						Changed = 1;
						Start_Placement();
					}
				} else {

					/*
					**	Place a trigger
					*/
					if (CurTrigger) {
						Place_Trigger();
						Changed = 1;
					} else {

						/*
						**	Select an object or a cell
						**	Check for double-click
						*/
						if (CurrentObject.Count() &&
							((TickCount - LastClickTime) < 15)) {
						;	// stub

						} else {
							/*
							**	Single-click: select object
							*/
							if (Select_Object()==0) {
								CurrentCell = 0;
								Grab_Object();
							} else {

								/*
								**	No object: select the cell
								*/
								CurrentCell = Click_Cell_Calc(Keyboard->MouseQX, Keyboard->MouseQY);
								HidPage.Clear();
								Flag_To_Redraw(true);
								Render();
							}
						}
					}
				}
				LastClickTime = TickCount();
				input = KN_NONE;
			} else {

				/*
				**	Left Button UP
				*/
				LMouseDown = 0;
				GrabbedObject = 0;
				input = KN_NONE;
			}
			break;

		/*
		**	SHIFT-ALT-Arrow: move the current object
		*/
		case (int)KN_UP | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
		case (int)KN_DOWN | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
		case (int)KN_LEFT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
		case (int)KN_RIGHT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
			if (CurrentObject.Count()) {
				CurrentObject[0]->Move(KN_To_Facing(input));
				Changed = 1;
			}
			input = KN_NONE;
			break;

		/*
		**	DELETE: delete currently-selected object
		*/
		case KN_DELETE:

			/*
			**	Delete currently-selected object's trigger, or the object
			*/
			if (CurrentObject.Count()) {

				/*
				**	Delete trigger
				*/
				if (CurrentObject[0]->Trigger.Is_Valid()) {
					CurrentObject[0]->Trigger = NULL;
				} else {
					/*
					** If the current object is part of the AI's Base, remove it
					** from the Base's Node list.
					*/
					if (CurrentObject[0]->What_Am_I()==RTTI_BUILDING &&
						Base.Is_Node((BuildingClass *)CurrentObject[0])) {
						node = Base.Get_Node((BuildingClass *)CurrentObject[0]);
						Base.Nodes.Delete(*node);
					}

					/*
					**	Delete current object
					*/
					delete CurrentObject[0];

					/*
					**	Hide the popup controls
					*/
					Popup_Controls();
				}

				/*
				**	Force a redraw
				*/
				HidPage.Clear();
				Flag_To_Redraw(true);
				Changed = 1;
			} else {

				/*
				**	Remove trigger from current cell
				*/
				if (CurrentCell) {
					if ((*this)[CurrentCell].Trigger.Is_Valid()) {
						(*this)[CurrentCell].Trigger = NULL;
//						CellTriggers[CurrentCell] = NULL;

						/*
						**	Force a redraw
						*/
						HidPage.Clear();
						Flag_To_Redraw(true);
						Changed = 1;
					}
				}
			}
			input = KN_NONE;
			break;

		/*
		**	TAB: select next object on the map
		*/
		case KN_TAB:
			Select_Next();
			input = KN_NONE;
			break;

		/*
		**	Object-Editing button: House Button
		*/
		case POPUP_HOUSELIST|KN_BUTTON:
			/*
			**	Determine the house desired by examining the currently
			**	selected index in the house list gadget.
			*/
			house = HousesType(((ListClass *)Buttons->Extract_Gadget(POPUP_HOUSELIST))->Current_Index());

			/*
			**	If that house doesn't own this object, try to transfer it
			*/
			if (CurrentObject[0]->Owner() != house) {
				if (Change_House(house)) {
					Changed = 1;
				}
			}
//			Set_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);
			HidPage.Clear();
			Buttons->Flag_List_To_Redraw();
			Flag_To_Redraw(true);
			input = KN_NONE;
			break;

//		case (POPUP_GDI | KN_BUTTON):
//		case (POPUP_NOD | KN_BUTTON):
//		case (POPUP_NEUTRAL | KN_BUTTON):
//		case (POPUP_MULTI1 | KN_BUTTON):
//		case (POPUP_MULTI2 | KN_BUTTON):
//		case (POPUP_MULTI3 | KN_BUTTON):
//		case (POPUP_MULTI4 | KN_BUTTON):
//
//			/*
//			**	Convert input value into a house value; assume HOUSE_GOOD is 0
//			*/
//			house = (HousesType)( (input & (~KN_BUTTON)) - POPUP_FIRST);
//
//			/*
//			**	If that house doesn't own this object, try to transfer it
//			*/
//			if (CurrentObject[0]->Owner()!=house) {
//				if (Change_House(house)) {
//					Changed = 1;
//				}
//			}
//			Set_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_FIRST);
//			HidPage.Clear();
//			Flag_To_Redraw(true);
//			input = KN_NONE;
//			break;

		case POPUP_SELLABLE|KN_BUTTON:
			if (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {
				BuildingClass * building = (BuildingClass *)CurrentObject[0];

				if (building->Class->Level != -1) {
//				if (building->Class->IsBuildable) {
					building->IsAllowedToSell = (building->IsAllowedToSell == false);
					building->Mark(MARK_CHANGE);
				}
				if (building->IsAllowedToSell) {
					Sellable->Turn_On();
				} else {
					Sellable->Turn_Off();
				}
			}
			break;

		case POPUP_REBUILDABLE|KN_BUTTON:
			if (CurrentObject[0]->What_Am_I() == RTTI_BUILDING) {
				BuildingClass * building = (BuildingClass *)CurrentObject[0];

				if (building->Class->Level != -1) {
//				if (building->Class->IsBuildable) {
					building->IsToRebuild = (building->IsToRebuild == false);
					building->Mark(MARK_CHANGE);
				}
				if (building->IsToRebuild) {
					Rebuildable->Turn_On();
				} else {
					Rebuildable->Turn_Off();
				}
			}
			break;

		/*
		**	Object-Editing button: Mission
		*/
		case (POPUP_MISSIONLIST | KN_BUTTON):
			if (CurrentObject[0]->Is_Techno()) {
				/*
				**	Set new mission
				*/
				mission = MapEditMissions[MissionList->Current_Index()];
				if (CurrentObject[0]->Get_Mission() != mission) {
					((TechnoClass *)CurrentObject[0])->Set_Mission(mission);
					Changed = 1;
					Buttons->Flag_List_To_Redraw();
					Flag_To_Redraw(true);
				}
			}
			input = KN_NONE;
			break;

		/*
		**	Object-Editing button: Health
		*/
		case (POPUP_HEALTHGAUGE | KN_BUTTON):
			if (CurrentObject[0]->Is_Techno()) {

				/*
				**	Derive strength from current gauge reading
				*/
				strength = CurrentObject[0]->Class_Of().MaxStrength * fixed(HealthGauge->Get_Value(), 256);
//				strength = Fixed_To_Cardinal((unsigned)CurrentObject[0]->Class_Of().MaxStrength, (unsigned)HealthGauge->Get_Value());

				/*
				**	Clip to 1
				*/
				if (strength <= 0) {
					strength = 1;
				}

				/*
				**	Set new strength
				*/
				if (strength != CurrentObject[0]->Strength) {
					CurrentObject[0]->Strength = strength;
					HidPage.Clear();
					Flag_To_Redraw(true);
					Changed = 1;
				}

				/*
				**	Update text label
				*/
				sprintf(HealthBuf, "%d", strength);
			}
			input = KN_NONE;
			break;

		/*
		**	Object-Editing button: Facing
		*/
		case (POPUP_FACINGDIAL | KN_BUTTON):
			if (CurrentObject[0]->Is_Techno()) {

				/*
				**	Set new facing
				*/
				if (FacingDial->Get_Direction() !=
					((TechnoClass *)CurrentObject[0])->PrimaryFacing.Get()) {

					/*
					**	Set body's facing
					*/
					((TechnoClass *)CurrentObject[0])->PrimaryFacing.Set(FacingDial->Get_Direction());

					/*
					**	Set turret facing, if there is one
					*/
					if (CurrentObject[0]->What_Am_I()==RTTI_UNIT) {
						((UnitClass *)CurrentObject[0])->SecondaryFacing.Set(FacingDial->Get_Direction());
					}

					HidPage.Clear();
					Flag_To_Redraw(true);
					Changed = 1;
				}
			}
			input = KN_NONE;
			break;

		/*
		**	Object-Editing button: Facing
		*/
		case (POPUP_BASEPERCENT | KN_BUTTON):
			if (BaseGauge->Get_Value() != Scen.Percent) {
				Scen.Percent = BaseGauge->Get_Value();
				Build_Base_To(Scen.Percent);
				HidPage.Clear();
				Flag_To_Redraw(true);
			}
			input = KN_NONE;
			break;

		default:
			break;
	}

	/*
	**	Call parent's AI routine
	*/
	MouseClass::AI(input, x, y);
}


/***************************************************************************
 * MapEditClass::Draw_It -- overloaded Redraw routine                      *
 *                                                                         *
 * INPUT:                                                                  *
 *                                                                         *
 * OUTPUT:                                                                 *
 *                                                                         *
 * WARNINGS:                                                               *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/17/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::Draw_It(bool forced)
{
	char const * label;
	char buf[40];
	char const * tptr;

	MouseClass::Draw_It(forced);

	if (!Debug_Map) {
		return;
	}

	/*
	**	Display the total value of all Tiberium on the map.
	*/
	Fancy_Text_Print("Tiberium=%ld   ", 0, 0, GadgetClass::Get_Color_Scheme(),
		BLACK, TPF_EFNT | TPF_NOSHADOW, TotalValue);

	/*
	**	If there are no object controls displayed, just invoke parent's Redraw
	**	and return.
	*/
	if (!Buttons) {
		return;
	}

	/*
	**	Otherwise, if 'display' is set, invoke the parent's Redraw to refresh
	**	the HIDPAGE; then, update the buttons & text labels onto HIDPAGE;
	**	then invoke the parent's Redraw to blit the HIDPAGE to SEENPAGE.
	*/
	if (forced) {

		/*
		**	Update the text labels
		*/
		if (CurrentObject.Count()) {
			/*
			**	Display the object's name & ID
			*/
			label = Text_String(CurrentObject[0]->Full_Name());
			tptr = label;
			sprintf(buf, "%s (%d)", tptr, CurrentObject[0]->As_Target());

			/*
			**	print the label
			*/
			Fancy_Text_Print (buf, 160, 0,
				&ColorRemaps[PCOLOR_BROWN], TBLACK,
				TPF_CENTER | TPF_NOSHADOW | TPF_EFNT);
		}
	}
}


/***************************************************************************
 * MapEditClass::Mouse_Moved -- checks for mouse motion                    *
 *                                                                         *
 * Reports whether the mouse has moved or not. This varies based on the    *
 * type of object currently selected. If there's an infantry object        *
 *   selected, mouse motion counts even within a cell; for all other types,*
 *   mouse motion counts only if the mouse changes cells.                  *
 *                                                                         *
 *   The reason this routine is needed is to prevent Paint-Mode from putting*
 *   gobs of trees and such into the same cell if the mouse moves just     *
 *   a little bit.                                                         *
 *                                                                         *
 * INPUT:                                                                  *
 *                                                                         *
 * OUTPUT:                                                                 *
 *                                                                         *
 * WARNINGS:                                                               *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/08/1994 BR : Created.                                              *
 *=========================================================================*/
bool MapEditClass::Mouse_Moved(void)
{
	static int old_mx = 0;
	static int old_my = 0;
	static CELL old_zonecell = 0;
	const ObjectTypeClass * objtype = NULL;
	bool retcode = false;

	/*
	**	Return if no motion
	*/
	if (old_mx == Get_Mouse_X() && old_my == Get_Mouse_Y()) {
		return(false);
	}

	/*
	**	Get a ptr to ObjectTypeClass
	*/
	if (PendingObject) {
		objtype = PendingObject;
	} else {
		if (GrabbedObject) {
			objtype = &GrabbedObject->Class_Of();
		} else {
			old_mx = Get_Mouse_X();
			old_my = Get_Mouse_Y();
			old_zonecell = ZoneCell;
			return(false);
		}
	}

	/*
	**	Infantry: mouse moved if any motion at all
	*/
	if (objtype->What_Am_I() == RTTI_INFANTRYTYPE) {
		retcode = true;
	} else {
		/*
		**	Others: mouse moved only if cell changed
		*/
		if (old_zonecell!=ZoneCell) {
			retcode = true;
		} else {
			retcode = false;
		}
	}

	old_mx = Get_Mouse_X();
	old_my = Get_Mouse_Y();
	old_zonecell = ZoneCell;
	return(retcode);
}


/***************************************************************************
 * MapEditClass::Main_Menu -- main menu processor for map editor           *
 *                                                                         *
 * INPUT:                                                                  *
 *      none.                                                              *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   10/20/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::Main_Menu(void)
{
	char const * _menus[MAX_MAIN_MENU_NUM + 1];
	int selection;						// option the user picks
	bool process;						// menu stays up while true
	int rc;

	/*
	**	Fill in menu items
	*/
	_menus[0] = "New Scenario";
	_menus[1] = "Load Scenario";
	_menus[2] = "Save Scenario";
	_menus[3] = "Size Map";
	_menus[4] = "Add Game Object";
	_menus[5] = "Scenario Options";
	_menus[6] = "AI Options";
	_menus[7] = "Play Scenario";
	_menus[8] = NULL;

	/*
	**	Main Menu loop
	*/
	Override_Mouse_Shape(MOUSE_NORMAL);	// display default mouse cursor
	process = true;
	while (process) {

		/*
		**	Invoke game callback, to update music
		*/
		Call_Back();

		/*
		**	Invoke menu
		*/
		Hide_Mouse();		// Do_Menu assumes the mouse is already hidden
		selection = Do_Menu(&_menus[0], true);
		Show_Mouse();
		if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
			break;
		}

		/*
		**	Process selection
		*/
		switch (selection) {

			/*
			**	New scenario
			*/
			case 0:
				if (Changed) {
					rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
					HidPage.Clear();
					Flag_To_Redraw(true);
					Render();
					if (rc==0) {
						if (Save_Scenario()!=0) {
							break;
						} else {
							Changed = 0;
						}
					}
				}
				if (New_Scenario()==0) {
					Scen.CarryOverMoney = 0;
					Changed = 1;
				}
				process = false;
				break;

			/*
			**	Load scenario
			*/
			case 1:
				if (Changed) {
					rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
					HidPage.Clear();
					Flag_To_Redraw(true);
					Render();
					if (rc==0) {
						if (Save_Scenario()!=0) {
							break;
						} else {
							Changed = 0;
						}
					}
				}
				if (Load_Scenario()==0) {
					Scen.CarryOverMoney = 0;
					Changed = 0;
				}
				process = false;
				break;

			/*
			**	Save scenario
			*/
			case 2:
				if (Save_Scenario() == 0) {
					Changed = 0;
				}
				process = false;
				break;

			/*
			**	Edit map size
			*/
			case 3:
				if (Size_Map(MapCellX, MapCellY, MapCellWidth, MapCellHeight)==0) {
					process = false;
					Changed = 1;
				}
				break;

			/*
			**	Add an object
			*/
			case 4:
				if (Placement_Dialog() == 0) {
					Start_Placement();
					process = false;
				}
				break;

			/*
			**	Scenario options
			*/
			case 5:
				if (Scenario_Dialog() == 0) {
					Changed = 1;
					process = false;
				}
				break;

			/*
			**	Other options
			*/
			case 6:
				AI_Menu();
				process = false;
				break;

			/*
			**	Test-drive this scenario
			*/
			case 7:
				if (Changed) {
					rc = WWMessageBox().Process("Save Changes?", TXT_YES, TXT_NO, TXT_CANCEL);
					HidPage.Clear();
					Flag_To_Redraw(true);
					Render();
					if (rc == 2) return;
					if (rc==0) {
						if (Save_Scenario()!=0) {
							break;
						} else {
							Changed = 0;
						}
					}
				}
				Changed = 0;
				Debug_Map = false;
				Start_Scenario(Scen.ScenarioName);
				return;
		}
	}

	/*
	**	Restore the display:
	**	- Clear HIDPAGE to erase any spurious drawing done by the menu system
	**	- Invoke Flag_To_Redraw to tell DisplayClass to re-render the whole screen
	**	- Invoke Redraw() to update the display
	*/
	HidPage.Clear();
	Flag_To_Redraw(true);
	Render();
}


/***************************************************************************
 * MapEditClass::AI_Menu -- menu of AI options                             *
 *                                                                         *
 * INPUT:                                                                  *
 *                                                                         *
 * OUTPUT:                                                                 *
 *                                                                         *
 * WARNINGS:                                                               *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/29/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::AI_Menu(void)
{
	int selection;						// option the user picks
	bool process;						// menu stays up while true
	char const * _menus[MAX_AI_MENU_NUM + 1];

	/*
	**	Fill in menu strings
	*/
	_menus[0] = "Pre-Build a Base";
	_menus[1] = "Edit Triggers";
	_menus[2] = "Edit Teams";
	_menus[3] = NULL;

	/*
	**	Main Menu loop
	*/
	Override_Mouse_Shape(MOUSE_NORMAL);		// display default mouse cursor
	process = true;
	while (process) {

		/*
		**	Invoke game callback, to update music
		*/
		Call_Back();

		/*
		**	Invoke menu
		*/
		Hide_Mouse();		// Do_Menu assumes the mouse is already hidden
		selection = Do_Menu(&_menus[0], true);
		Show_Mouse();
		if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
			break;
		}

		/*
		**	Process selection
		*/
		switch (selection) {
			/*
			**	Pre-Build a Base
			*/
			case 0:
				Start_Base_Building();
				process = false;
				break;

			/*
			**	Trigger Editing
			*/
			case 1:
				Handle_Triggers();
				/*
				**	Go into trigger placement mode
				*/
				if (CurTrigger) {
					Start_Trigger_Placement();
				}
				process = false;
				break;

			/*
			**	Team Editing
			*/
			case 2:
				Handle_Teams("Teams");
				process = false;
				break;
		}
	}
}


/***************************************************************************
 * MapEditClass::Verify_House -- is this objtype ownable by this house?    *
 *                                                                         *
 * INPUT:                                                                  *
 *      house         house to check                                       *
 *      objtype      ObjectTypeClass to check                              *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      0 = isn't ownable, 1 = it is                                       *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/16/1994 BR : Created.                                              *
 *=========================================================================*/
bool MapEditClass::Verify_House(HousesType house, ObjectTypeClass const * objtype)
{
	/*
	**	Verify that new house can own this object
	*/
	return((objtype->Get_Ownable() & (1 << house)) != 0);
}


/***************************************************************************
 * MapEditClass::Cycle_House -- finds next valid house for object type     *
 *                                                                         *
 * INPUT:                                                                  *
 *      objtype      ObjectTypeClass ptr to get house for                  *
 *      curhouse      current house value to start with                    *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      HousesType that's valid for this object type                       *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/23/1994 BR : Created.                                              *
 *=========================================================================*/
HousesType MapEditClass::Cycle_House(HousesType curhouse, ObjectTypeClass const *)
{
	HousesType count;			// prevents an infinite loop

	/*
	**	Loop through all house types, starting with the one after 'curhouse';
	**	return the first one that's valid
	*/
	count = HOUSE_NONE;
	while (1) {

		/*
		**	Go to next house
		*/
		curhouse++;
		if (curhouse == HOUSE_COUNT) {
			curhouse = HOUSE_FIRST;
		}

		/*
		**	Count # iterations; don't go forever
		*/
		count++;
		if (count == HOUSE_COUNT) {
			curhouse = HOUSE_NONE;
			break;
		}

		/*
		**	Break if this is a valid house
		*/
//		if (HouseClass::As_Pointer(curhouse) && Verify_House(curhouse, objtype)) {
			break;
//		}
	}

	return(curhouse);
}


/***************************************************************************
 * MapEditClass::Fatal -- exits with error message                         *
 *                                                                         *
 * INPUT:                                                                  *
 *      code      tells which message to display; this minimizes the       *
 *               use of character strings in the code.                     *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   12/12/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::Fatal(int txt)
{
	//Prog_End();
	printf("%s\n", txt);
	Emergency_Exit(EXIT_FAILURE);
}


bool MapEditClass::Scroll_Map(DirType facing, int & distance, bool really)
{
	if (Debug_Map) {
		/*
		** The popup gadgets require the entire map to be redrawn if we scroll.
		*/
		if (really) {
			Flag_To_Redraw(true);
		}
	}
	return(MouseClass::Scroll_Map(facing, distance, really));
}


#ifdef OBSOLETE
void MapEditClass::Flag_To_Redraw(bool complete)
{
	MouseClass::Flag_To_Redraw(complete);
}
#endif


void MapEditClass::Detach(ObjectClass * object)
{
	if (GrabbedObject == object) {
		GrabbedObject = 0;
	}
}

bool MapEditClass::Get_Waypoint_Name(char wayptname[])
{
	/*
	**	Dialog & button dimensions
	*/
	enum {
		D_DIALOG_W = 100,											// dialog width
		D_DIALOG_H = 56,											// dialog height
		D_DIALOG_X = ((320 - D_DIALOG_W) / 2),				// centered x-coord
		D_DIALOG_Y = ((200 - D_DIALOG_H) / 2),				// centered y-coord
		D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),		// coord of x-center

		D_TXT8_H = 11,												// ht of 8-pt text
		D_MARGIN = 7,												// margin width/height

		D_EDIT_W = D_DIALOG_W - (D_MARGIN * 2),
		D_EDIT_H = 13,
		D_EDIT_X = D_DIALOG_X + D_MARGIN,
		D_EDIT_Y = D_DIALOG_Y + 20,

		D_BUTTON_X = D_DIALOG_X + D_MARGIN,
		D_BUTTON_Y = D_DIALOG_Y + 40,
		D_BUTTON_W = 40,
		D_BUTTON_H = 13,

		D_CANCEL_X = D_DIALOG_X + 53,
		D_CANCEL_Y = D_DIALOG_Y + 40,
		D_CANCEL_W = 40,
		D_CANCEL_H = 13,

	};

	/*
	**	Button enumerations
	*/
	enum {
		BUTTON_OK = 100,
		BUTTON_CANCEL,
		BUTTON_EDIT,
	};

	/*
	**	Dialog variables
	*/
	bool cancel = false;						// true = user cancels
	wayptname[0] = 0;

	/*
	**	Buttons
	*/
	ControlClass * commands = NULL;		// the button list

	TextButtonClass button (BUTTON_OK, TXT_OK, TPF_EBUTTON, D_BUTTON_X, D_BUTTON_Y, D_BUTTON_W);
	TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_EBUTTON, D_CANCEL_X, D_CANCEL_Y, D_CANCEL_W);
	EditClass editbtn (BUTTON_EDIT, wayptname, 3, TPF_EFNT|TPF_NOSHADOW, D_EDIT_X, D_EDIT_Y, D_EDIT_W, -1, EditClass::ALPHANUMERIC);

	/*
	**	Initialize.
	*/
	Set_Logic_Page(SeenBuff);

	/*
	**	Create the button list.
	*/
	commands = &button;
	cancelbtn.Add_Tail(*commands);
	editbtn.Add_Tail(*commands);
	editbtn.Set_Focus();

	/*
	**	Main Processing Loop.
	*/
	bool firsttime = true;
	bool display = true;
	bool process = true;
	while (process) {

		/*
		**	Invoke game callback.
		*/
		if (Session.Type == GAME_NORMAL) {
			Call_Back();
		} else if (Main_Loop()) {
			process = false;
			cancel = true;
		}

		/*
		**	Refresh display if needed.
		*/
		if (display) {

			/*
			**	Display the dialog box.
			*/
			Hide_Mouse();
			if (display) {
				Dialog_Box(D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W, D_DIALOG_H);
//				Draw_Caption(caption, D_DIALOG_X, D_DIALOG_Y, D_DIALOG_W);

			}

			/*
			**	Redraw the buttons.
			*/
			if (display) {
				commands->Flag_List_To_Redraw();
			}
			Show_Mouse();
			display = false;
		}

		/*
		**	Get user input.
		*/
		KeyNumType input = commands->Input();

		/*
		**	The first time through the processing loop, set the edit
		**	gadget to have the focus. The
		**	focus must be set here since the gadget list has changed
		**	and this change will cause any previous focus setting to be
		**	cleared by the input processing routine.
		*/
		if (firsttime) {
			firsttime = false;
			editbtn.Set_Focus();
			editbtn.Flag_To_Redraw();
		}

		/*
		**	If the <RETURN> key was pressed, then default to the appropriate
		**	action button according to the style of this dialog box.
		*/
		if (input == KN_RETURN) {
			input = (KeyNumType)(BUTTON_OK|KN_BUTTON);
		}

		/*
		**	Process input.
		*/
		switch (input) {
			/*
			** Load: if load fails, present a message, and stay in the dialog
			** to allow the user to try another game
			*/
			case (BUTTON_OK | KN_BUTTON):
				Hide_Mouse();
				SeenPage.Clear();
				GamePalette.Set();
				Show_Mouse();
				process = false;
				cancel = false;
				break;

			/*
			** ESC/Cancel: break
			*/
			case (KN_ESC):
			case (BUTTON_CANCEL | KN_BUTTON):
				Hide_Mouse();
				SeenPage.Clear();
				GamePalette.Set();
				Show_Mouse();
				cancel = true;
				process = false;
				break;

			default:
				break;
		}
	}

	Map.Flag_To_Redraw(true);
	if (cancel) return(false);

	return(true);
}

void MapEditClass::Update_Waypoint(int waypt_idx)
{
	CELL cell;

	/*
	**	Unflag cell for this waypoint if there is one
	*/
	cell = Scen.Waypoint[waypt_idx];
	if (cell != -1) {
		if (Scen.Waypoint[WAYPT_HOME] != cell && Scen.Waypoint[WAYPT_REINF] != cell) {
			(*this)[cell].IsWaypoint = 0;
		}
		Flag_Cell(cell);
	}
	Scen.Waypoint[waypt_idx] = CurrentCell;
	(*this)[CurrentCell].IsWaypoint = 1;
	Changed = 1;
	Flag_Cell(CurrentCell);
}


/***************************************************************************
 * MapEditClass::Read_INI -- overloaded Read_INI function                  *
 *                                                                         *
 * Overloading this function gives the map editor a chance to initialize   *
 * certain values every time a new INI is read.                            *
 *                                                                         *
 * INPUT:                                                                  *
 *      buffer      INI staging area                                       *
 *                                                                         *
 * OUTPUT:                                                                 *
 *      none.                                                              *
 *                                                                         *
 * WARNINGS:                                                               *
 *      none.                                                              *
 *                                                                         *
 * HISTORY:                                                                *
 *   11/16/1994 BR : Created.                                              *
 *=========================================================================*/
void MapEditClass::Read_INI(CCINIClass & ini)
{
	/*
	**	Invoke parent's Read_INI
	*/
	Mono_Printf("We are in Read_INI\n");

	MouseClass::Read_INI(ini);
	BaseGauge->Set_Value(Scen.Percent);

	Mono_Clear_Screen();
	Mono_Printf("Scen.Percent = %d", Scen.Percent);

//	BaseGauge->Set_Value(Scen.Percent);
}


void MapEditClass::Write_INI(CCINIClass & ini)
{
	MouseClass::Write_INI(ini);
//	ini.Put_Int("Basic", "Percent", Scen.Percent);
}

#endif

#include	"mapedsel.cpp"