CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

MAPEDIT.CPP (70638B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\mapedit.cpv   2.18   16 Oct 1995 16:48:40   JOE_BOSTIC  $ */
     17 /***************************************************************************
     18  **   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        **
     19  ***************************************************************************
     20  *                                                                         *
     21  *                 Project Name : Command & Conquer                        *
     22  *                                                                         *
     23  *                    File Name : MAPEDIT.CPP                              *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : October 20, 1994                         *
     28  *                                                                         *
     29  *                  Last Update : February 2, 1995   [BR]                  *
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  *   Map Editor overloaded routines & utility routines                     *
     33  *-------------------------------------------------------------------------*
     34  * Map Editor modules:                                                     *
     35  * (Yes, they're all one huge class.)                                      *
     36  *      mapedit.cpp:   overloaded routines, utility routines               *
     37  *      mapeddlg.cpp:   map editor dialogs, most of the main menu options  *
     38  *      mapedplc.cpp:   object-placing routines                            *
     39  *      mapedsel.cpp:   object-selection & manipulation routines           *
     40  *      mapedtm.cpp:   team-editing routines                               *
     41  *-------------------------------------------------------------------------*
     42  * Functions:                                                              *
     43  *   MapEditClass::MapEditClass -- class constructor                       *
     44  *   MapEditClass::One_Time -- one-time initialization                     *
     45  *   MapEditClass::Read_INI -- overloaded Read_INI function                *
     46  *   MapEditClass::Clear_List -- clears the internal choosable object list *
     47  *   MapEditClass::Add_To_List -- adds a TypeClass to the choosable list   *
     48  *   MapEditClass::AI -- The map editor's main logic                       *
     49  *   MapEditClass::Draw_It -- overloaded Redraw routine                    *
     50  *   MapEditClass::Main_Menu -- main menu processor for map editor         *
     51  *   MapEditClass::AI_Menu -- menu of AI options                           *
     52  *   MapEditClass::Mouse_Moved -- checks for mouse motion                  *
     53  *   MapEditClass::Verify_House -- sees if given house can own given obj   *
     54  *   MapEditClass::Cycle_House -- finds next valid house for object type   *
     55  *   MapEditClass::Trigger_Needs_Team -- tells if a trigger needs a team   *
     56  *   MapEditClass::Fatal -- exits with error message                       *
     57  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     58 
     59 #include	"function.h"
     60 
     61 #ifdef SCENARIO_EDITOR
     62 
     63 /*
     64 ****************************** Globals/Externs ******************************
     65 */
     66 /*...........................................................................
     67 Array of all missions supported by the map editor
     68 ...........................................................................*/
     69 MissionType MapEditClass::MapEditMissions[] = {
     70 	MISSION_GUARD,
     71 	MISSION_STICKY,
     72 	MISSION_HARVEST,
     73 	MISSION_GUARD_AREA,
     74 	MISSION_RETURN,
     75 	MISSION_AMBUSH,
     76 	MISSION_HUNT,
     77 	MISSION_SLEEP,
     78 };
     79 #define NUM_EDIT_MISSIONS (sizeof(MapEditClass::MapEditMissions) / sizeof(MapEditClass::MapEditMissions[0]))
     80 
     81 
     82 /*...........................................................................
     83 For menu processing
     84 ...........................................................................*/
     85 extern int UnknownKey;					// in menus.cpp
     86 
     87 char MapEditClass::HealthBuf[20];
     88 
     89 
     90 /***************************************************************************
     91  * MapEditClass::MapEditClass -- class constructor                         *
     92  *                                                                         *
     93  * INPUT:                                                                  *
     94  *      none.                                                              *
     95  *                                                                         *
     96  * OUTPUT:                                                                 *
     97  *      none.                                                              *
     98  *                                                                         *
     99  * WARNINGS:                                                               *
    100  *      none.                                                              *
    101  *                                                                         *
    102  * HISTORY:                                                                *
    103  *   10/20/1994 BR : Created.                                              *
    104  *=========================================================================*/
    105 MapEditClass::MapEditClass(void)
    106 {
    107 	/*
    108 	**	Init data members.
    109 	*/
    110 	ScenVar = SCEN_VAR_A;
    111 	ObjCount = 0;
    112 	LastChoice = 0;
    113 	LastHouse = HOUSE_GOOD;
    114 	GrabbedObject = 0;
    115 	for (int i=0; i < NUM_EDIT_CLASSES; i++) {
    116 		NumType[i] = 0;
    117 		TypeOffset[i] = 0;
    118 	}
    119 	Waypoint[WAYPT_HOME] = 0;
    120 	CurrentCell = 0;
    121 	CurTrigger = NULL;
    122 	Changed = 0;
    123 	LMouseDown = 0;
    124 	BaseBuilding = 0;
    125 	BasePercent = 100;
    126 }
    127 
    128 
    129 /***************************************************************************
    130  * MapEditClass::One_Time -- one-time initialization                       *
    131  *                                                                         *
    132  * INPUT:                                                                  *
    133  *      none.                                                              *
    134  *                                                                         *
    135  * OUTPUT:                                                                 *
    136  *      none.                                                              *
    137  *                                                                         *
    138  * WARNINGS:                                                               *
    139  *      none.                                                              *
    140  *                                                                         *
    141  * HISTORY:                                                                *
    142  *   02/02/1995 BR : Created.                                              *
    143  *=========================================================================*/
    144 void MapEditClass::One_Time(void)
    145 {
    146 	MouseClass::One_Time();
    147 
    148 	/*------------------------------------------------------------------------
    149 	Create the pop-up controls
    150 	------------------------------------------------------------------------*/
    151 	/*........................................................................
    152 	The map: a single large "button"
    153 	........................................................................*/
    154 	//MapArea = new ControlClass(MAP_AREA,0,8,312,192, GadgetClass::LEFTPRESS |
    155 		//GadgetClass::LEFTRELEASE, false);
    156 	MapArea = new ControlClass(MAP_AREA,0,16,624,384, GadgetClass::LEFTPRESS |
    157 		GadgetClass::LEFTRELEASE, false);
    158 
    159 	/*........................................................................
    160 	House buttons
    161 	........................................................................*/
    162 	GDIButton = new TextButtonClass (POPUP_GDI, "GDI",
    163 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    164 		POPUP_GDI_X, POPUP_GDI_Y, POPUP_GDI_W, POPUP_GDI_H);
    165 
    166 	NODButton = new TextButtonClass (POPUP_NOD, "NOD",
    167 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    168 		POPUP_NOD_X, POPUP_NOD_Y, POPUP_NOD_W, POPUP_NOD_H);
    169 
    170 	NeutralButton = new TextButtonClass (POPUP_NEUTRAL, "Neutral",
    171 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    172 		POPUP_NEUTRAL_X, POPUP_NEUTRAL_Y, POPUP_NEUTRAL_W, POPUP_NEUTRAL_H);
    173 
    174 	Multi1Button = new TextButtonClass (POPUP_MULTI1, "M1",
    175 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    176 		POPUP_MULTI1_X, POPUP_MULTI1_Y, POPUP_MULTI1_W, POPUP_MULTI1_H);
    177 
    178 	Multi2Button = new TextButtonClass (POPUP_MULTI2, "M2",
    179 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    180 		POPUP_MULTI2_X, POPUP_MULTI2_Y, POPUP_MULTI2_W, POPUP_MULTI2_H);
    181 
    182 	Multi3Button = new TextButtonClass (POPUP_MULTI3, "M3",
    183 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    184 		POPUP_MULTI3_X, POPUP_MULTI3_Y, POPUP_MULTI3_W, POPUP_MULTI3_H);
    185 
    186 	Multi4Button = new TextButtonClass (POPUP_MULTI4, "M4",
    187 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    188 		POPUP_MULTI4_X, POPUP_MULTI4_Y, POPUP_MULTI4_W, POPUP_MULTI4_H);
    189 
    190 	/*........................................................................
    191 	The mission list box
    192 	........................................................................*/
    193 	MissionList = new ListClass (POPUP_MISSIONLIST,
    194 		POPUP_MISSION_X, POPUP_MISSION_Y, POPUP_MISSION_W, POPUP_MISSION_H,
    195 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    196 		Hires_Retrieve("BTN-UP.SHP"),
    197 		Hires_Retrieve("BTN-DN.SHP"));
    198 
    199 	for (int i = 0; i < NUM_EDIT_MISSIONS; i++) {
    200 		MissionList->Add_Item (MissionClass::Mission_Name(MapEditMissions[i]));
    201 	}
    202 
    203 	/*........................................................................
    204 	The health bar
    205 	........................................................................*/
    206 	HealthGauge = new TriColorGaugeClass (POPUP_HEALTHGAUGE,
    207 		POPUP_HEALTH_X, POPUP_HEALTH_Y, POPUP_HEALTH_W, POPUP_HEALTH_H);
    208 	HealthGauge->Use_Thumb(true);
    209 	HealthGauge->Set_Maximum(0x100);
    210 	HealthGauge->Set_Red_Limit(0x3f - 1);
    211 	HealthGauge->Set_Yellow_Limit(0x7f - 1);
    212 
    213 	/*........................................................................
    214 	The health text label
    215 	........................................................................*/
    216 	HealthBuf[0] = 0;
    217 	HealthText = new TextLabelClass (HealthBuf,
    218 		POPUP_HEALTH_X + POPUP_HEALTH_W / 2,
    219 		POPUP_HEALTH_Y + POPUP_HEALTH_H + 1,
    220 		CC_GREEN, TPF_CENTER | TPF_FULLSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
    221 
    222 	/*........................................................................
    223 	The facing dial
    224 	........................................................................*/
    225 	FacingDial = new Dial8Class (POPUP_FACINGDIAL, POPUP_FACEBOX_X,
    226 		POPUP_FACEBOX_Y, POPUP_FACEBOX_W, POPUP_FACEBOX_H, (DirType)0);
    227 
    228 	/*........................................................................
    229 	The base percent-built slider & its label
    230 	........................................................................*/
    231 	BaseGauge = new GaugeClass (POPUP_BASEPERCENT,
    232 		POPUP_BASE_X, POPUP_BASE_Y, POPUP_BASE_W, POPUP_BASE_H);
    233 	BaseLabel = new TextLabelClass ("Base:", POPUP_BASE_X - 3, POPUP_BASE_Y,
    234 		CC_GREEN, TPF_RIGHT | TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
    235 	BaseGauge->Set_Maximum(100);
    236 	BaseGauge->Set_Value(BasePercent);
    237 }
    238 
    239 
    240 /***********************************************************************************************
    241  * MapeditClass::Init_IO -- Reinitializes the radar map at scenario start.                     *
    242  *                                                                                             *
    243  * INPUT:   none                                                                               *
    244  *                                                                                             *
    245  * OUTPUT:  none                                                                               *
    246  *                                                                                             *
    247  * WARNINGS:   none                                                                            *
    248  *                                                                                             *
    249  * HISTORY:                                                                                    *
    250  *   12/22/1994 JLB : Created.                                                                 *
    251  *=============================================================================================*/
    252 void MapEditClass::Init_IO(void)
    253 {
    254 	/*------------------------------------------------------------------------
    255 	For normal game mode, jump to the parent's Init routine.
    256 	------------------------------------------------------------------------*/
    257 	if (!Debug_Map) {
    258 
    259 		MouseClass::Init_IO();
    260 
    261 	} else {
    262 
    263 		/*------------------------------------------------------------------------
    264 		For editor mode, add the map area to the button input list
    265 		------------------------------------------------------------------------*/
    266 		Buttons = 0;
    267 		Add_A_Button(*BaseGauge);
    268 		Add_A_Button(*BaseLabel);
    269 		Add_A_Button(*MapArea);
    270 	}
    271 }
    272 
    273 
    274 /***************************************************************************
    275  * MapEditClass::Read_INI -- overloaded Read_INI function                  *
    276  *                                                                         *
    277  * Overloading this function gives the map editor a chance to initialize   *
    278  * certain values every time a new INI is read.                            *
    279  *                                                                         *
    280  * INPUT:                                                                  *
    281  *      buffer      INI staging area                                       *
    282  *                                                                         *
    283  * OUTPUT:                                                                 *
    284  *      none.                                                              *
    285  *                                                                         *
    286  * WARNINGS:                                                               *
    287  *      none.                                                              *
    288  *                                                                         *
    289  * HISTORY:                                                                *
    290  *   11/16/1994 BR : Created.                                              *
    291  *=========================================================================*/
    292 void MapEditClass::Read_INI(char *buffer)
    293 {
    294 	/*
    295 	------------------------ Invoke parent's Read_INI ------------------------
    296 	*/
    297 	MouseClass::Read_INI(buffer);
    298 
    299 	BasePercent = WWGetPrivateProfileInt("Basic","Percent",0,buffer);
    300 	BaseGauge->Set_Value(BasePercent);
    301 }
    302 
    303 
    304 /***************************************************************************
    305  * MapEditClass::Write_INI -- overloaded Read_INI function                 *
    306  *                                                                         *
    307  * INPUT:                                                                  *
    308  *      buffer      INI staging area                                       *
    309  *                                                                         *
    310  * OUTPUT:                                                                 *
    311  *      none.                                                              *
    312  *                                                                         *
    313  * WARNINGS:                                                               *
    314  *      none.                                                              *
    315  *                                                                         *
    316  * HISTORY:                                                                *
    317  *   11/16/1994 BR : Created.                                              *
    318  *=========================================================================*/
    319 void MapEditClass::Write_INI(char *buffer)
    320 {
    321 	/*
    322 	----------------------- Invoke parent's Write_INI ------------------------
    323 	*/
    324 	MouseClass::Write_INI(buffer);
    325 
    326 	/*
    327 	** Save the base's percent-built value; this must be saved into the BASIC
    328 	** section of the INI, since the Base section will be entirely erased
    329 	** by the Base's Write_INI routine.
    330 	*/
    331 	WWWritePrivateProfileInt("Basic", "Percent", BasePercent, buffer);
    332 }
    333 
    334 
    335 /***************************************************************************
    336  * MapEditClass::Clear_List -- clears the internal choosable object list   *
    337  *                                                                         *
    338  * INPUT:                                                                  *
    339  *      none.                                                              *
    340  *                                                                         *
    341  * OUTPUT:                                                                 *
    342  *      none.                                                              *
    343  *                                                                         *
    344  * WARNINGS:                                                               *
    345  *      none.                                                              *
    346  *                                                                         *
    347  * HISTORY:                                                                *
    348  *   10/20/1994 BR : Created.                                              *
    349  *=========================================================================*/
    350 void MapEditClass::Clear_List(void)
    351 {
    352 	/*------------------------------------------------------------------------
    353 	Set # object type ptrs to 0, set NumType for each type to 0
    354 	------------------------------------------------------------------------*/
    355 	ObjCount = 0;
    356 	for (int i = 0; i < NUM_EDIT_CLASSES; i++) {
    357 		NumType[i] = 0;
    358 	}
    359 }
    360 
    361 
    362 /***************************************************************************
    363  * MapEditClass::Add_To_List -- adds a TypeClass to the choosable list     *
    364  *                                                                         *
    365  * Use this routine to add an object to the game object selection list.    *
    366  * This list is used by the Add_Object function. All items located in the  *
    367  * list will appear and be chooseable by that function. Make sure to       *
    368  * clear the list before adding a sequence of items to it. Clearing        *
    369  * the list is accomplished by the Clear_List() function.                  *
    370  *                                                                         *
    371  * INPUT:                                                                  *
    372  *      object      ptr to ObjectTypeClass to add                          *
    373  *                                                                         *
    374  * OUTPUT:                                                                 *
    375  *      bool: was the object added to the list?  A failure could occur if  *
    376  *      NULL were passed in or the list is full.                           *
    377  *                                                                         *
    378  * WARNINGS:                                                               *
    379  *      none.                                                              *
    380  *                                                                         *
    381  * HISTORY:                                                                *
    382  *   06/04/1994 JLB : Created.                                             *
    383  *=========================================================================*/
    384 bool MapEditClass::Add_To_List(ObjectTypeClass const *object)
    385 {
    386 	/*
    387 	**	Add the object if there's room.
    388 	*/
    389 	if (object && ObjCount < MAX_EDIT_OBJECTS) {
    390 		Objects[ObjCount++] = object;
    391 
    392 		/*
    393 		**	Update type counters.
    394 		*/
    395 		switch (object->What_Am_I()) {
    396 			case RTTI_TEMPLATETYPE:
    397 				NumType[0]++;
    398 				break;
    399 
    400 			case RTTI_OVERLAYTYPE:
    401 				NumType[1]++;
    402 				break;
    403 
    404 			case RTTI_SMUDGETYPE:
    405 				NumType[2]++;
    406 				break;
    407 
    408 			case RTTI_TERRAINTYPE:
    409 				NumType[3]++;
    410 				break;
    411 
    412 			case RTTI_UNITTYPE:
    413 				NumType[4]++;
    414 				break;
    415 
    416 			case RTTI_INFANTRYTYPE:
    417 				NumType[5]++;
    418 				break;
    419 
    420 			case RTTI_AIRCRAFTTYPE:
    421 				NumType[6]++;
    422 				break;
    423 
    424 			case RTTI_BUILDINGTYPE:
    425 				NumType[7]++;
    426 				break;
    427 		}
    428 		return(true);
    429 	}
    430 
    431 	return(false);
    432 }
    433 
    434 
    435 /***************************************************************************
    436  * MapEditClass::AI -- The map editor's main logic                         *
    437  *                                                                         *
    438  * This routine overloads the parent's (DisplayClass) AI function.         *
    439  * It checks for any input specific to map editing, and calls the parent   *
    440  * AI routine to handle scrolling and other mainstream map stuff.          *
    441  *                                                                         *
    442  * If this detects one of its special input keys, it sets 'input' to 0     *
    443  * before calling the parent AI routine; this prevents input conflict.     *
    444  *                                                                         *
    445  * SUPPORTED INPUT:                                                        *
    446  * General:                                                                *
    447  *      F2/RMOUSE:            main menu                                    *
    448  *      F6:                  toggles show-passable mode                    *
    449  *      HOME:                  go to the Home Cell (scenario's start position)*
    450  *      SHIFT-HOME:            set the Home Cell to the current TacticalCell*
    451  *      ESC:                  exits to DOS                                 *
    452  * Object Placement:                                                       *
    453  *      INSERT:               go into placement mode                       *
    454  *      ESC:                  exit placement mode                          *
    455  *      LEFT/RIGHT:          prev/next placement object                    *
    456  *      PGUP/PGDN:            prev/next placement category                 *
    457  *      HOME:                  1st placement object (clear template)       *
    458  *      h/H:                  toggle house of placement object             *
    459  *      LMOUSE:               place the placement object                   *
    460  *      MOUSE MOTION:         "paint" with the placement object            *
    461  * Object selection:                                                       *
    462  *      LMOUSE:               select & "grab" current object               *
    463  *                           If no object is present where the mouse is    *
    464  *                           clicked, the current object is de-selected    *
    465  *                           If the same object is clicked on, it stays    *
    466  *                           selected. Also displays the object-editing    *
    467  *                           gadgets.                                      *
    468  *      LMOUSE RLSE:         release currently-grabbed object              *
    469  *      MOUSE MOTION:         if an object is grabbed, moves the object    *
    470  *      SHIFT|ALT|ARROW:      moves object in that direction               *
    471  *      DELETE               deletes currently-selected object             *
    472  * Object-editing controls:                                                *
    473  *      POPUP_GDI:            makes GDI the owner of this object           *
    474  *      POPUP_NOD:            makes NOD the owner of this object           *
    475  *      POPUP_MISSIONLIST:   sets that mission for this object             *
    476  *      POPUP_HEALTHGAUGE:   sets that health value for this object        *
    477  *      POPUP_FACINGDIAL:      sets the object's facing                    *
    478  *                                                                         *
    479  * Changed is set when you:                                                *
    480  *      - place an object                                                  *
    481  *      - move a grabbed object                                            *
    482  *      - delete an object                                                 *
    483  *      - size the map                                                     *
    484  *      - create a new scenario                                            *
    485  *   Changed is cleared when you:                                          *
    486  *      - Save the scenario                                                *
    487  *      - Load a scenario                                                  *
    488  *      - Play the scenario                                                *
    489  *                                                                         *
    490  * INPUT:                                                                  *
    491  *      input      KN_ value, 0 if none                                    *
    492  *                                                                         *
    493  * OUTPUT:                                                                 *
    494  *      none.                                                              *
    495  *                                                                         *
    496  * WARNINGS:                                                               *
    497  *      none.                                                              *
    498  *                                                                         *
    499  * HISTORY:                                                                *
    500  *   10/20/1994 BR : Created.                                              *
    501  *=========================================================================*/
    502 void MapEditClass::AI(KeyNumType &input, int x, int y)
    503 {
    504 	int rc;
    505 	MissionType mission;
    506 	int strength;
    507 	CELL cell;
    508 	int i;
    509 	int found;									// for removing a waypoint label
    510 	int waypt_idx;								// for labelling a waypoint
    511 	BaseNodeClass *node;						// for removing from an AI Base
    512 	HousesType house;
    513 
    514 	/*------------------------------------------------------------------------
    515 	Trap 'F2' regardless of whether we're in game or editor mode
    516 	------------------------------------------------------------------------*/
    517 	if (Debug_Flag) {
    518 		if (/*(input == KN_F2 && Session == GAME_SOLO) ||*/ input == (KN_F2 | KN_CTRL_BIT)) {
    519 			ScenarioInit = 0;
    520 
    521 			/*
    522 			** If we're in editor mode & Changed is set, prompt for saving changes
    523 			*/
    524 			if (Debug_Map && Changed) {
    525 				rc = CCMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
    526 				HiddenPage.Clear();
    527 				Flag_To_Redraw(true);
    528 				Render();
    529 				/*
    530 				........................ User wants to save ........................
    531 				*/
    532 				if (rc == 0) {
    533 
    534 					/*
    535 					................ If save cancelled, abort game ..................
    536 					*/
    537 					if (Save_Scenario()!=0) {
    538 						input = KN_NONE;
    539 					} else {
    540 						Changed = 0;
    541 						Go_Editor(!Debug_Map);
    542 					}
    543 				} else {
    544 
    545 					/*
    546 					.................... User doesn't want to save .....................
    547 					*/
    548 					Go_Editor(!Debug_Map);
    549 				}
    550 			} else {
    551 				/*
    552 				** If we're in game mode, set Changed to 0 (so if we didn't save our
    553 				** changes above, they won't keep coming back to haunt us with continual
    554 				** Save Changes? prompts!)
    555 				*/
    556 				if (!Debug_Map) {
    557 					Changed = 0;
    558 				}
    559 				Go_Editor(!Debug_Map);
    560 			}
    561 		}
    562 	}
    563 
    564 	/*------------------------------------------------------------------------
    565 	For normal game mode, jump to the parent's AI routine.
    566 	------------------------------------------------------------------------*/
    567 	if (!Debug_Map) {
    568 		MouseClass::AI(input, x, y);
    569 		return;
    570 	}
    571 
    572 	::Frame++;
    573 
    574 	/*------------------------------------------------------------------------
    575 	Do special mouse processing if the mouse is over the map
    576 	------------------------------------------------------------------------*/
    577 	if (Get_Mouse_X() > TacPixelX && Get_Mouse_X() <
    578 		TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
    579 		Get_Mouse_Y() > TacPixelY && Get_Mouse_Y() <
    580 		TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {
    581 		/*.....................................................................
    582 		When the mouse moves over a scrolling edge, ScrollClass changes its
    583 		shape to the appropriate arrow or NO symbol; it's our job to change it
    584 		back to normal (or whatever the shape is set to by Set_Default_Mouse())
    585 		when it re-enters the map area.
    586 		.....................................................................*/
    587 		if (CurTrigger) {
    588 			Override_Mouse_Shape(MOUSE_CAN_MOVE);
    589 		} else {
    590 			Override_Mouse_Shape(MOUSE_NORMAL);
    591 		}
    592 	}
    593 
    594 	/*.....................................................................
    595 	Set 'ZoneCell' to track the mouse cursor around over the map.  Do this
    596 	even if the map is scrolling.
    597 	.....................................................................*/
    598 	if (Get_Mouse_X() >= TacPixelX && Get_Mouse_X() <=
    599 		TacPixelX + Lepton_To_Pixel(TacLeptonWidth) &&
    600 		Get_Mouse_Y() >= TacPixelY && Get_Mouse_Y() <=
    601 		TacPixelY + Lepton_To_Pixel(TacLeptonHeight)) {
    602 
    603 		cell = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());
    604 		if (cell != -1) {
    605 			Set_Cursor_Pos(cell);
    606 			if (PendingObject) {
    607 				Flag_To_Redraw(true);
    608 			}
    609 		}
    610 	}
    611 
    612 	/*------------------------------------------------------------------------
    613 	Check for mouse motion while left button is down.
    614 	------------------------------------------------------------------------*/
    615 	rc = Mouse_Moved();
    616 	if (LMouseDown && rc) {
    617 		/*.....................................................................
    618 		"Paint" mode: place current object, and restart placement
    619 		.....................................................................*/
    620 		if (PendingObject) {
    621 			Flag_To_Redraw(true);
    622 			if (Place_Object() == 0) {
    623 				Changed = 1;
    624 				Start_Placement();
    625 			}
    626 		} else {
    627 			/*.....................................................................
    628 			Move the currently-grabbed object
    629 			.....................................................................*/
    630 			if (GrabbedObject) {
    631 				GrabbedObject->Mark(MARK_CHANGE);
    632 				if (Move_Grabbed_Object() == 0) {
    633 					Changed = 1;
    634 				}
    635 			}
    636 		}
    637 	}
    638 
    639 	/*------------------------------------------------------------------------
    640 	Trap special editing keys; if one is detected, set 'input' to 0 to
    641 	prevent a conflict with parent's AI().
    642 	------------------------------------------------------------------------*/
    643 	switch (input) {
    644 		/*---------------------------------------------------------------------
    645 		F2/RMOUSE = pop up main menu
    646 		---------------------------------------------------------------------*/
    647 		case KN_RMOUSE:
    648 			/*
    649 			..................... Turn off placement mode ......................
    650 			*/
    651 			if (PendingObject) {
    652 				if (BaseBuilding) {
    653 					Cancel_Base_Building();
    654 				} else {
    655 					Cancel_Placement();
    656 				}
    657 			}
    658 
    659 			/*
    660 			................. Turn off trigger placement mode ..................
    661 			*/
    662 			if (CurTrigger) {
    663 				Stop_Trigger_Placement();
    664 			}
    665 
    666 			/*
    667 			.............. Unselect object & hide popup controls ...............
    668 			*/
    669 			if (CurrentObject.Count()) {
    670 				CurrentObject[0]->Unselect();
    671 				Popup_Controls();
    672 			}
    673 			Main_Menu();
    674 			input = KN_NONE;
    675 			break;
    676 
    677 		/*---------------------------------------------------------------------
    678 		F6 = toggle passable/impassable display
    679 		---------------------------------------------------------------------*/
    680 		case KN_F6:
    681 			Debug_Passable = (Debug_Passable == false);
    682 			HiddenPage.Clear();
    683 			Flag_To_Redraw(true);
    684 			input = KN_NONE;
    685 			break;
    686 
    687 		/*---------------------------------------------------------------------
    688 		INSERT = go into object-placement mode
    689 		---------------------------------------------------------------------*/
    690 		case KN_INSERT:
    691 			if (!PendingObject) {
    692 				/*
    693 				......... Unselect current object, hide popup controls ..........
    694 				*/
    695 				if (CurrentObject.Count()) {
    696 					CurrentObject[0]->Unselect();
    697 					Popup_Controls();
    698 				}
    699 				/*
    700 				.................... Go into placement mode .....................
    701 				*/
    702 				Start_Placement();
    703 			}
    704 			input = KN_NONE;
    705 			break;
    706 
    707 		/*---------------------------------------------------------------------
    708 		ESC = exit placement mode, or exit to DOS
    709 		---------------------------------------------------------------------*/
    710 		case KN_ESC:
    711 
    712 			/*
    713 			.................... Exit object placement mode ....................
    714 			*/
    715 			if (PendingObject) {
    716 				if (BaseBuilding) {
    717 					Cancel_Base_Building();
    718 				} else {
    719 					Cancel_Placement();
    720 				}
    721 				input = KN_NONE;
    722 				break;
    723 			} else {
    724 
    725 				/*
    726 				................... Exit trigger placement mode ....................
    727 				*/
    728 				if (CurTrigger) {
    729 					Stop_Trigger_Placement();
    730 					input = KN_NONE;
    731 					break;
    732 				} else {
    733 					rc = CCMessageBox().Process("Exit Scenario Editor?", TXT_YES, TXT_NO);
    734 					HiddenPage.Clear();
    735 					Flag_To_Redraw(true);
    736 					Render();
    737 
    738 					/*
    739 					.......... User doesn't want to exit; return to editor ..........
    740 					*/
    741 					if (rc==1) {
    742 						input = KN_NONE;
    743 						break;
    744 					}
    745 
    746 					/*
    747 					................. If changed, prompt for saving .................
    748 					*/
    749 					if (Changed) {
    750 						rc = CCMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
    751 						HiddenPage.Clear();
    752 						Flag_To_Redraw(true);
    753 						Render();
    754 
    755 						/*
    756 						..................... User wants to save .....................
    757 						*/
    758 						if (rc == 0) {
    759 
    760 							/*
    761 							.............. If save cancelled, abort exit ..............
    762 							*/
    763 							if (Save_Scenario()!=0) {
    764 								input = KN_NONE;
    765 								break;
    766 							} else {
    767 								Changed = 0;
    768 							}
    769 						}
    770 					}
    771 				}
    772 			}
    773 			Prog_End();
    774 			exit (0);
    775 			break;
    776 
    777 		/*---------------------------------------------------------------------
    778 		LEFT = go to previous placement object
    779 		---------------------------------------------------------------------*/
    780 		case KN_LEFT:
    781 			if (PendingObject) {
    782 				Place_Prev();
    783 			}
    784 			input = KN_NONE;
    785 			break;
    786 
    787 		/*---------------------------------------------------------------------
    788 		RIGHT = go to next placement object
    789 		---------------------------------------------------------------------*/
    790 		case KN_RIGHT:
    791 			if (PendingObject) {
    792 				Place_Next();
    793 			}
    794 			input = KN_NONE;
    795 			break;
    796 
    797 		/*---------------------------------------------------------------------
    798 		PGUP = go to previous placement category
    799 		---------------------------------------------------------------------*/
    800 		case KN_PGUP:
    801 			if (PendingObject) {
    802 				Place_Prev_Category();
    803 			}
    804 			input = KN_NONE;
    805 			break;
    806 
    807 		/*---------------------------------------------------------------------
    808 		PGDN = go to next placement category
    809 		---------------------------------------------------------------------*/
    810 		case KN_PGDN:
    811 			if (PendingObject) {
    812 				Place_Next_Category();
    813 			}
    814 			input = KN_NONE;
    815 			break;
    816 
    817 		/*---------------------------------------------------------------------
    818 		HOME = jump to first placement object, or go to Home Cell
    819 		---------------------------------------------------------------------*/
    820 		case KN_HOME:
    821 			if (PendingObject) {
    822 				Place_Home();
    823 			} else {
    824 
    825 				/*
    826 				....................... Set map position ........................
    827 				*/
    828 				ScenarioInit++;
    829 				Set_Tactical_Position(Waypoint[WAYPT_HOME]);
    830 				ScenarioInit--;
    831 
    832 				/*
    833 				...................... Force map to redraw ......................
    834 				*/
    835 				HiddenPage.Clear();
    836 				Flag_To_Redraw(true);
    837 				Render();
    838 			}
    839 			input = KN_NONE;
    840 			break;
    841 
    842 		/*---------------------------------------------------------------------
    843 		SHIFT-HOME: set new Home Cell position
    844 		---------------------------------------------------------------------*/
    845 		case ((int)KN_HOME | (int)KN_SHIFT_BIT):
    846 			/*
    847 			** Unflag the old Home Cell, if there are no other waypoints
    848 			** pointing to it
    849 			*/
    850 			cell = Waypoint[WAYPT_HOME];
    851 
    852 			if (cell != -1) {
    853 				found = 0;
    854 				for (i = 0; i < WAYPT_COUNT; i++) {
    855 					if (i != WAYPT_HOME && Waypoint[i]==cell) {
    856 						found = 1;
    857 					}
    858 				}
    859 
    860 				if (found==0) {
    861 					(*this)[cell].IsWaypoint = 0;
    862 					Flag_Cell(cell);
    863 				}
    864 
    865 			}
    866 
    867 			/*
    868 			** Now set the new Home cell
    869 			*/
    870 			Waypoint[WAYPT_HOME] = Coord_Cell(TacticalCoord);
    871 			(*this)[Coord_Cell(TacticalCoord)].IsWaypoint = 1;
    872 			Flag_Cell(Coord_Cell(TacticalCoord));
    873 			Changed = 1;
    874 			input = KN_NONE;
    875 			break;
    876 
    877 		/*---------------------------------------------------------------------
    878 		SHIFT-R: set new Reinforcement Cell position.  Don't allow setting
    879 		the Reinf. Cell to the same as the Home Cell (for display purposes.)
    880 		---------------------------------------------------------------------*/
    881 		case ((int)KN_R | (int)KN_SHIFT_BIT):
    882 			if (CurrentCell==0 || CurrentCell==Waypoint[WAYPT_HOME]) {
    883 				break;
    884 			}
    885 
    886 			/*
    887 			** Unflag the old Reinforcement Cell, if there are no other waypoints
    888 			** pointing to it
    889 			*/
    890 			cell = Waypoint[WAYPT_REINF];
    891 
    892 			if (cell != -1) {
    893 				found = 0;
    894 				for (i = 0; i < WAYPT_COUNT; i++) {
    895 					if (i != WAYPT_REINF && Waypoint[i]==cell) {
    896 						found = 1;
    897 					}
    898 				}
    899 
    900 				if (found==0) {
    901 					(*this)[cell].IsWaypoint = 0;
    902 					Flag_Cell(cell);
    903 				}
    904 
    905 			}
    906 			/*
    907 			** Now set the new Reinforcement cell
    908 			*/
    909 			Waypoint[WAYPT_REINF] = CurrentCell;
    910 			(*this)[CurrentCell].IsWaypoint = 1;
    911 			Flag_Cell(CurrentCell);
    912 			Changed = 1;
    913 			input = KN_NONE;
    914 			break;
    915 
    916 		/*---------------------------------------------------------------------
    917 		ALT-Letter: Label a waypoint cell
    918 		---------------------------------------------------------------------*/
    919 		case ((int)KN_A | (int)KN_ALT_BIT):
    920 		case ((int)KN_B | (int)KN_ALT_BIT):
    921 		case ((int)KN_C | (int)KN_ALT_BIT):
    922 		case ((int)KN_D | (int)KN_ALT_BIT):
    923 		case ((int)KN_E | (int)KN_ALT_BIT):
    924 		case ((int)KN_F | (int)KN_ALT_BIT):
    925 		case ((int)KN_G | (int)KN_ALT_BIT):
    926 		case ((int)KN_H | (int)KN_ALT_BIT):
    927 		case ((int)KN_I | (int)KN_ALT_BIT):
    928 		case ((int)KN_J | (int)KN_ALT_BIT):
    929 		case ((int)KN_K | (int)KN_ALT_BIT):
    930 		case ((int)KN_L | (int)KN_ALT_BIT):
    931 		case ((int)KN_M | (int)KN_ALT_BIT):
    932 		case ((int)KN_N | (int)KN_ALT_BIT):
    933 		case ((int)KN_O | (int)KN_ALT_BIT):
    934 		case ((int)KN_P | (int)KN_ALT_BIT):
    935 		case ((int)KN_Q | (int)KN_ALT_BIT):
    936 		case ((int)KN_R | (int)KN_ALT_BIT):
    937 		case ((int)KN_S | (int)KN_ALT_BIT):
    938 		case ((int)KN_T | (int)KN_ALT_BIT):
    939 		case ((int)KN_U | (int)KN_ALT_BIT):
    940 		case ((int)KN_V | (int)KN_ALT_BIT):
    941 		case ((int)KN_W | (int)KN_ALT_BIT):
    942 		case ((int)KN_X | (int)KN_ALT_BIT):
    943 		case ((int)KN_Y | (int)KN_ALT_BIT):
    944 		case ((int)KN_Z | (int)KN_ALT_BIT):
    945 			if (CurrentCell != 0) {
    946 				waypt_idx = KN_To_KA(input & 0xff) - KA_a;
    947 				/*...............................................................
    948 				Unflag cell for this waypoint if there is one
    949 				...............................................................*/
    950 				cell = Waypoint[waypt_idx];
    951 				if (cell != -1) {
    952 					if (Waypoint[WAYPT_HOME] != cell &&
    953 						Waypoint[WAYPT_REINF] != cell)
    954 						(*this)[cell].IsWaypoint = 0;
    955 					Flag_Cell(cell);
    956 				}
    957 				Waypoint[waypt_idx] = CurrentCell;
    958 				(*this)[CurrentCell].IsWaypoint = 1;
    959 				Changed = 1;
    960 				Flag_Cell(CurrentCell);
    961 			}
    962 			input = KN_NONE;
    963 			break;
    964 
    965 		/*---------------------------------------------------------------------
    966 		ALT-1-4: Designate a cell as a capture-the-flag cell.
    967 		---------------------------------------------------------------------*/
    968 		case ((int)KN_1 | (int)KN_ALT_BIT):
    969 		case ((int)KN_2 | (int)KN_ALT_BIT):
    970 		case ((int)KN_3 | (int)KN_ALT_BIT):
    971 		case ((int)KN_4 | (int)KN_ALT_BIT):
    972 			/*------------------------------------------------------------------
    973 			If there's a current cell, place the flag & waypoint there.
    974 			------------------------------------------------------------------*/
    975 			if (CurrentCell != 0) {
    976 				waypt_idx = (KN_To_KA(input & 0xff) - KA_1);
    977 				house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
    978 				if (HouseClass::As_Pointer(house)) {
    979 					HouseClass::As_Pointer(house)->Flag_Attach(CurrentCell,true);
    980 				}
    981 			} else {
    982 				/*------------------------------------------------------------------
    983 				If there's a current object, attach the flag to it and clear the
    984 				waypoint.
    985 				------------------------------------------------------------------*/
    986 				if (CurrentObject[0] != 0) {
    987 					waypt_idx = (KN_To_KA(input & 0xff) - KA_1);
    988 					house = (HousesType)(HOUSE_MULTI1 + waypt_idx);
    989 					if (HouseClass::As_Pointer(house) && CurrentObject[0]->What_Am_I() == RTTI_UNIT) {
    990 						HouseClass::As_Pointer(house)->Flag_Attach((UnitClass *)CurrentObject[0], true);
    991 					}
    992 				}
    993 			}
    994 			input = KN_NONE;
    995 			break;
    996 
    997 		/*---------------------------------------------------------------------
    998 		ALT-Space: Remove a waypoint designation
    999 		---------------------------------------------------------------------*/
   1000 		case ((int)KN_SPACE | (int)KN_ALT_BIT):
   1001 			if (CurrentCell != 0) {
   1002 				/*...............................................................
   1003 				Loop through letter waypoints; if this cell is one of them,
   1004 				clear that waypoint.
   1005 				...............................................................*/
   1006 				for (i = 0 ; i < 26; i++) {
   1007 					if (Waypoint[i]==CurrentCell)
   1008 						Waypoint[i] = -1;
   1009 				}
   1010 
   1011 				/*...............................................................
   1012 				Loop through flag home values; if this cell is one of them, clear
   1013 				that waypoint.
   1014 				...............................................................*/
   1015 				for (i = 0; i < MAX_PLAYERS; i++) {
   1016 					house = (HousesType)(HOUSE_MULTI1 + i);
   1017 					if (HouseClass::As_Pointer(house) &&
   1018 						CurrentCell == HouseClass::As_Pointer(house)->FlagHome)
   1019 					HouseClass::As_Pointer(house)->Flag_Remove(As_Target(CurrentCell),true);
   1020 				}
   1021 
   1022 				/*...............................................................
   1023 				If there are no more waypoints on this cell, clear the cell's
   1024 				waypoint designation.
   1025 				...............................................................*/
   1026 				if (Waypoint[WAYPT_HOME]!=CurrentCell &&
   1027 					Waypoint[WAYPT_REINF]!=CurrentCell)
   1028 					(*this)[CurrentCell].IsWaypoint = 0;
   1029 				Changed = 1;
   1030 				Flag_Cell(CurrentCell);
   1031 			}
   1032 			input = KN_NONE;
   1033 			break;
   1034 
   1035 		/*---------------------------------------------------------------------
   1036 		'H' = toggle current placement object's house
   1037 		---------------------------------------------------------------------*/
   1038 		case KN_H:
   1039 		case ((int)KN_H | (int)KN_SHIFT_BIT):
   1040 			if (PendingObject) {
   1041 				Toggle_House();
   1042 			}
   1043 			input = KN_NONE;
   1044 			break;
   1045 
   1046 		/*---------------------------------------------------------------------
   1047 		Left-mouse click:
   1048 		Button DOWN:
   1049 		- Toggle LMouseDown
   1050 		- If we're in placement mode, try to place the current object
   1051 		  - If success, re-enter placement mode
   1052 		- Otherwise, try to select an object, and "grab" it if there is one
   1053 		- If no object, then select that cell as the "current" cell
   1054 		Button UP:
   1055 		- Toggle LMouseDown
   1056 		- release any grabbed object
   1057 		---------------------------------------------------------------------*/
   1058 		case ((int)MAP_AREA | (int)KN_BUTTON):
   1059 			/*
   1060 			------------------------- Left Button DOWN -------------------------
   1061 			*/
   1062 			if (Keyboard::Down(KN_LMOUSE)) {
   1063 				LMouseDown = 1;
   1064 				/*
   1065 				............... Placement mode: place an object .................
   1066 				*/
   1067 				if (PendingObject) {
   1068 					if (Place_Object()==0) {
   1069 						Changed = 1;
   1070 						Start_Placement();
   1071 					}
   1072 				} else {
   1073 					/*
   1074 					....................... Place a trigger .........................
   1075 					*/
   1076 					if (CurTrigger) {
   1077 						Place_Trigger();
   1078 						Changed = 1;
   1079 					}  else {
   1080 						/*
   1081 						................. Select an object or a cell .................
   1082 						.................. Check for double-click ....................
   1083 						*/
   1084 						if (CurrentObject.Count() &&
   1085 							( (TickCount.Time() - LastClickTime) < 15)) {
   1086 						;	// stub
   1087 
   1088 						} else {
   1089 							/*
   1090 							................ Single-click: select object .................
   1091 							*/
   1092 							if (Select_Object()==0) {
   1093 								CurrentCell = 0;
   1094 								Grab_Object();
   1095 							} else {
   1096 								/*
   1097 								................ No object: select the cell ..................
   1098 								*/
   1099 								CurrentCell = Click_Cell_Calc(_Kbd->MouseQX,_Kbd->MouseQY);
   1100 								HiddenPage.Clear();
   1101 								Flag_To_Redraw(true);
   1102 								Render();
   1103 							}
   1104 						}
   1105 					}
   1106 				}
   1107 				LastClickTime = TickCount.Time();
   1108 				input = KN_NONE;
   1109 			} else {
   1110 
   1111 				/*
   1112 				-------------------------- Left Button UP --------------------------
   1113 				*/
   1114 				LMouseDown = 0;
   1115 				GrabbedObject = 0;
   1116 				input = KN_NONE;
   1117 			}
   1118 			break;
   1119 
   1120 		/*---------------------------------------------------------------------
   1121 		SHIFT-ALT-Arrow: move the current object
   1122 		---------------------------------------------------------------------*/
   1123 		case (int)KN_UP | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
   1124 		case (int)KN_DOWN | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
   1125 		case (int)KN_LEFT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
   1126 		case (int)KN_RIGHT | (int)KN_ALT_BIT | (int)KN_SHIFT_BIT:
   1127 			if (CurrentObject.Count()) {
   1128 				CurrentObject[0]->Move(KN_To_Facing(input));
   1129 				Changed = 1;
   1130 			}
   1131 			input = KN_NONE;
   1132 			break;
   1133 
   1134 		/*---------------------------------------------------------------------
   1135 		DELETE: delete currently-selected object
   1136 		---------------------------------------------------------------------*/
   1137 		case KN_DELETE:
   1138 			/*..................................................................
   1139 			Delete currently-selected object's trigger, or the object
   1140 			..................................................................*/
   1141 			if (CurrentObject.Count()) {
   1142 
   1143 				/*
   1144 				........................ Delete trigger .........................
   1145 				*/
   1146 				if (CurrentObject[0]->Trigger) {
   1147 					CurrentObject[0]->Trigger = NULL;
   1148 				} else {
   1149 					/*
   1150 					** If the current object is part of the AI's Base, remove it
   1151 					** from the Base's Node list.
   1152 					*/
   1153 					if (CurrentObject[0]->What_Am_I()==RTTI_BUILDING &&
   1154 						Base.Is_Node((BuildingClass *)CurrentObject[0])) {
   1155 						node = Base.Get_Node((BuildingClass *)CurrentObject[0]);
   1156 						Base.Nodes.Delete(*node);
   1157 					}
   1158 
   1159 					/*
   1160 					................... Delete current object ....................
   1161 					*/
   1162 					delete CurrentObject[0];
   1163 
   1164 					/*
   1165 					.................. Hide the popup controls ...................
   1166 					*/
   1167 					Popup_Controls();
   1168 				}
   1169 
   1170 				/*
   1171 				........................ Force a redraw .........................
   1172 				*/
   1173 				HiddenPage.Clear();
   1174 				Flag_To_Redraw(true);
   1175 				Changed = 1;
   1176 			} else {
   1177 				/*
   1178 				................. Remove trigger from current cell .................
   1179 				*/
   1180 				if (CurrentCell) {
   1181 					if ((*this)[CurrentCell].IsTrigger) {
   1182 						(*this)[CurrentCell].IsTrigger = 0;
   1183 						CellTriggers[CurrentCell] = NULL;
   1184 						/*
   1185 						...................... Force a redraw ........................
   1186 						*/
   1187 						HiddenPage.Clear();
   1188 						Flag_To_Redraw(true);
   1189 						Changed = 1;
   1190 					}
   1191 				}
   1192 			}
   1193 			input = KN_NONE;
   1194 			break;
   1195 
   1196 		/*---------------------------------------------------------------------
   1197 		TAB: select next object on the map
   1198 		---------------------------------------------------------------------*/
   1199 		case KN_TAB:
   1200 			Select_Next();
   1201 			input = KN_NONE;
   1202 			break;
   1203 
   1204 		/*---------------------------------------------------------------------
   1205 		Object-Editing button: House Button
   1206 		---------------------------------------------------------------------*/
   1207 		case (POPUP_GDI | KN_BUTTON):
   1208 		case (POPUP_NOD | KN_BUTTON):
   1209 		case (POPUP_NEUTRAL | KN_BUTTON):
   1210 		case (POPUP_MULTI1 | KN_BUTTON):
   1211 		case (POPUP_MULTI2 | KN_BUTTON):
   1212 		case (POPUP_MULTI3 | KN_BUTTON):
   1213 		case (POPUP_MULTI4 | KN_BUTTON):
   1214 			/*..................................................................
   1215 			Convert input value into a house value; assume HOUSE_GOOD is 0
   1216 			..................................................................*/
   1217 			house = (HousesType)( (input & (~KN_BUTTON)) - POPUP_GDI);
   1218 			/*..................................................................
   1219 			If that house doesn't own this object, try to transfer it
   1220 			..................................................................*/
   1221 			if (CurrentObject[0]->Owner()!=house) {
   1222 				if (Change_House(house)) {
   1223 					Changed = 1;
   1224 				}
   1225 			}
   1226 			Set_House_Buttons(CurrentObject[0]->Owner(), Buttons, POPUP_GDI);
   1227 			HiddenPage.Clear();
   1228 			Flag_To_Redraw(true);
   1229 			input = KN_NONE;
   1230 			break;
   1231 
   1232 		/*---------------------------------------------------------------------
   1233 		Object-Editing button: Mission
   1234 		---------------------------------------------------------------------*/
   1235 		case (POPUP_MISSIONLIST | KN_BUTTON):
   1236 			if (CurrentObject[0]->Is_Techno()) {
   1237 				/*
   1238 				........................ Set new mission ........................
   1239 				*/
   1240 				mission = MapEditMissions[MissionList->Current_Index()];
   1241 				if (CurrentObject[0]->Get_Mission() != mission) {
   1242 					((TechnoClass *)CurrentObject[0])->Set_Mission(mission);
   1243 					Changed = 1;
   1244 				}
   1245 			}
   1246 			Flag_To_Redraw(true);
   1247 			input = KN_NONE;
   1248 			break;
   1249 
   1250 		/*---------------------------------------------------------------------
   1251 		Object-Editing button: Health
   1252 		---------------------------------------------------------------------*/
   1253 		case (POPUP_HEALTHGAUGE | KN_BUTTON):
   1254 			if (CurrentObject[0]->Is_Techno()) {
   1255 				/*
   1256 				.......... Derive strength from current gauge reading ...........
   1257 				*/
   1258 				strength = Fixed_To_Cardinal(
   1259 					(unsigned)CurrentObject[0]->Class_Of().MaxStrength,
   1260 					(unsigned)HealthGauge->Get_Value());
   1261 
   1262 				/*
   1263 				........................... Clip to 1 ...........................
   1264 				*/
   1265 				if (strength <= 0) {
   1266 					strength = 1;
   1267 				}
   1268 
   1269 				/*
   1270 				....................... Set new strength ........................
   1271 				*/
   1272 				if (strength != CurrentObject[0]->Strength) {
   1273 					CurrentObject[0]->Strength = strength;
   1274 					HiddenPage.Clear();
   1275 					Flag_To_Redraw(true);
   1276 					Changed = 1;
   1277 				}
   1278 
   1279 				/*
   1280 				....................... Update text label .......................
   1281 				*/
   1282 				sprintf(HealthBuf,"%d",strength);
   1283 			}
   1284 			input = KN_NONE;
   1285 			break;
   1286 
   1287 		/*---------------------------------------------------------------------
   1288 		Object-Editing button: Facing
   1289 		---------------------------------------------------------------------*/
   1290 		case (POPUP_FACINGDIAL | KN_BUTTON):
   1291 			if (CurrentObject[0]->Is_Techno()) {
   1292 				/*
   1293 				........................ Set new facing .........................
   1294 				*/
   1295 				if (FacingDial->Get_Direction() !=
   1296 					((TechnoClass *)CurrentObject[0])->PrimaryFacing.Get()) {
   1297 					/*
   1298 					..................... Set body's facing ......................
   1299 					*/
   1300 					((TechnoClass *)CurrentObject[0])->PrimaryFacing.Set(FacingDial->Get_Direction());
   1301 
   1302 					/*
   1303 					............. Set turret facing, if there is one .............
   1304 					*/
   1305 					if (CurrentObject[0]->What_Am_I()==RTTI_UNIT) {
   1306 						((UnitClass *)CurrentObject[0])->SecondaryFacing.Set(FacingDial->Get_Direction());
   1307 					}
   1308 
   1309 					HiddenPage.Clear();
   1310 					Flag_To_Redraw(true);
   1311 					Changed = 1;
   1312 				}
   1313 			}
   1314 			input = KN_NONE;
   1315 			break;
   1316 
   1317 		/*---------------------------------------------------------------------
   1318 		Object-Editing button: Facing
   1319 		---------------------------------------------------------------------*/
   1320 		case (POPUP_BASEPERCENT | KN_BUTTON):
   1321 			if (BaseGauge->Get_Value() != BasePercent) {
   1322 				BasePercent = BaseGauge->Get_Value();
   1323 				Build_Base_To(BasePercent);
   1324 				HiddenPage.Clear();
   1325 				Flag_To_Redraw(true);
   1326 			}
   1327 			input = KN_NONE;
   1328 			break;
   1329 
   1330 		case (KN_LMOUSE):
   1331 			input = KN_NONE;
   1332 			break;
   1333 
   1334 		default:
   1335 			break;
   1336 	}
   1337 
   1338 	/*
   1339 	------------------------ Call parent's AI routine ------------------------
   1340 	*/
   1341 	MouseClass::AI(input, x, y);
   1342 }
   1343 
   1344 
   1345 /***************************************************************************
   1346  * MapEditClass::Draw_It -- overloaded Redraw routine                      *
   1347  *                                                                         *
   1348  * INPUT:                                                                  *
   1349  *                                                                         *
   1350  * OUTPUT:                                                                 *
   1351  *                                                                         *
   1352  * WARNINGS:                                                               *
   1353  *                                                                         *
   1354  * HISTORY:                                                                *
   1355  *   11/17/1994 BR : Created.                                              *
   1356  *=========================================================================*/
   1357 void MapEditClass::Draw_It(bool forced)
   1358 {
   1359 	char const *label;
   1360 	char buf[40];
   1361 	char const *tptr;
   1362 
   1363 	MouseClass::Draw_It(forced);
   1364 
   1365 	if (!Debug_Map) {
   1366 		return;
   1367 	}
   1368 
   1369 	//
   1370 	// Erase scrags at top of screen
   1371 	//
   1372 	LogicPage->Fill_Rect(0, 0, 640, 16, BLACK);
   1373 
   1374 	/*
   1375 	**	Display the total value of all Tiberium on the map.
   1376 	*/
   1377 	Fancy_Text_Print("Tiberium=%ld   ", 0, 0, CC_GREEN, BLACK,
   1378 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW, TotalValue);
   1379 
   1380 	/*------------------------------------------------------------------------
   1381 	If there are no object controls displayed, just invoke parent's Redraw
   1382 	and return.
   1383 	------------------------------------------------------------------------*/
   1384 	if (!Buttons) {
   1385 		return;
   1386 	}
   1387 
   1388 	/*------------------------------------------------------------------------
   1389 	Otherwise, if 'display' is set, invoke the parent's Redraw to refresh
   1390 	the HIDPAGE; then, update the buttons & text labels onto HIDPAGE;
   1391 	then invoke the parent's Redraw to blit the HIDPAGE to SEENPAGE.
   1392 	------------------------------------------------------------------------*/
   1393 	if (forced) {
   1394 
   1395 		/*
   1396 		....................... Update the text labels ........................
   1397 		*/
   1398 		if (CurrentObject.Count()) {
   1399 			/*
   1400 			------------------ Display the object's name & ID ------------------
   1401 			*/
   1402 			label = Text_String(CurrentObject[0]->Full_Name());
   1403 			tptr = label;
   1404 			sprintf(buf,"%s (%d)",tptr,CurrentObject[0]->As_Target());
   1405 
   1406 			/*
   1407 			......................... print the label ..........................
   1408 			*/
   1409 			Fancy_Text_Print (buf, 320, 0, CC_TAN, TBLACK,
   1410 				TPF_CENTER | TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   1411 		}
   1412 	}
   1413 }
   1414 
   1415 
   1416 /***************************************************************************
   1417  * MapEditClass::Mouse_Moved -- checks for mouse motion                    *
   1418  *                                                                         *
   1419  * Reports whether the mouse has moved or not. This varies based on the    *
   1420  * type of object currently selected. If there's an infantry object        *
   1421  *   selected, mouse motion counts even within a cell; for all other types,*
   1422  *   mouse motion counts only if the mouse changes cells.                  *
   1423  *                                                                         *
   1424  *   The reason this routine is needed is to prevent Paint-Mode from putting*
   1425  *   gobs of trees and such into the same cell if the mouse moves just     *
   1426  *   a little bit.                                                         *
   1427  *                                                                         *
   1428  * INPUT:                                                                  *
   1429  *                                                                         *
   1430  * OUTPUT:                                                                 *
   1431  *                                                                         *
   1432  * WARNINGS:                                                               *
   1433  *                                                                         *
   1434  * HISTORY:                                                                *
   1435  *   11/08/1994 BR : Created.                                              *
   1436  *=========================================================================*/
   1437 bool MapEditClass::Mouse_Moved(void)
   1438 {
   1439 	static int old_mx = 0;
   1440 	static int old_my = 0;
   1441 	static CELL old_zonecell = 0;
   1442 	const ObjectTypeClass * objtype = NULL;
   1443 	bool retcode = false;
   1444 
   1445 	/*
   1446 	-------------------------- Return if no motion ---------------------------
   1447 	*/
   1448 	if (old_mx == Get_Mouse_X() && old_my == Get_Mouse_Y()) {
   1449 		return(false);
   1450 	}
   1451 
   1452 	/*
   1453 	---------------------- Get a ptr to ObjectTypeClass ----------------------
   1454 	*/
   1455 	if (PendingObject) {
   1456 		objtype = PendingObject;
   1457 	} else {
   1458 		if (GrabbedObject) {
   1459 			objtype = &GrabbedObject->Class_Of();
   1460 		} else {
   1461 			old_mx = Get_Mouse_X();
   1462 			old_my = Get_Mouse_Y();
   1463 			old_zonecell = ZoneCell;
   1464 			return(false);
   1465 		}
   1466 	}
   1467 
   1468 	/*
   1469 	--------------------- Check for motion based on type ---------------------
   1470 	*/
   1471 	/*
   1472 	............... Infantry: mouse moved if any motion at all ...............
   1473 	*/
   1474 	if (objtype->What_Am_I() == RTTI_INFANTRYTYPE) {
   1475 		retcode = true;
   1476 	} else {
   1477 		/*
   1478 		................ Others: mouse moved only if cell changed ................
   1479 		*/
   1480 		if (old_zonecell!=ZoneCell) {
   1481 			retcode = true;
   1482 		} else {
   1483 			retcode = false;
   1484 		}
   1485 	}
   1486 
   1487 	old_mx = Get_Mouse_X();
   1488 	old_my = Get_Mouse_Y();
   1489 	old_zonecell = ZoneCell;
   1490 	return(retcode);
   1491 }
   1492 
   1493 
   1494 /***************************************************************************
   1495  * MapEditClass::Main_Menu -- main menu processor for map editor           *
   1496  *                                                                         *
   1497  * INPUT:                                                                  *
   1498  *      none.                                                              *
   1499  *                                                                         *
   1500  * OUTPUT:                                                                 *
   1501  *      none.                                                              *
   1502  *                                                                         *
   1503  * WARNINGS:                                                               *
   1504  *      none.                                                              *
   1505  *                                                                         *
   1506  * HISTORY:                                                                *
   1507  *   10/20/1994 BR : Created.                                              *
   1508  *=========================================================================*/
   1509 void MapEditClass::Main_Menu(void)
   1510 {
   1511 	char const *_menus[MAX_MAIN_MENU_NUM + 1];
   1512 	int selection;						// option the user picks
   1513 	bool process;						// menu stays up while true
   1514 	int rc;
   1515 
   1516 	/*
   1517 	--------------------------- Fill in menu items ---------------------------
   1518 	*/
   1519 	_menus[0] = "New Scenario";
   1520 	_menus[1] = "Load Scenario";
   1521 	_menus[2] = "Save Scenario";
   1522 	_menus[3] = "Size Map";
   1523 	_menus[4] = "Add Game Object";
   1524 	_menus[5] = "Scenario Options";
   1525 	_menus[6] = "AI Options";
   1526 	_menus[7] = "Play Scenario";
   1527 	_menus[8] = NULL;
   1528 
   1529 	/*
   1530 	----------------------------- Main Menu loop -----------------------------
   1531 	*/
   1532 	Override_Mouse_Shape(MOUSE_NORMAL);	// display default mouse cursor
   1533 	process = true;
   1534 	while (process) {
   1535 
   1536 		/*
   1537 		................ Invoke game callback, to update music ................
   1538 		*/
   1539 		Call_Back();
   1540 
   1541 		/*
   1542 		............................. Invoke menu .............................
   1543 		*/
   1544 		Hide_Mouse();		// Do_Menu assumes the mouse is already hidden
   1545 		selection = Do_Menu(&_menus[0], true);
   1546 		Show_Mouse();
   1547 		if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
   1548 			break;
   1549 		}
   1550 
   1551 		/*
   1552 		.......................... Process selection ..........................
   1553 		*/
   1554 		switch (selection) {
   1555 			/*
   1556 			........................... New scenario ...........................
   1557 			*/
   1558 			case 0:
   1559 				if (Changed) {
   1560 					rc = CCMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
   1561 					HiddenPage.Clear();
   1562 					Flag_To_Redraw(true);
   1563 					Render();
   1564 					if (rc==0) {
   1565 						if (Save_Scenario()!=0) {
   1566 							break;
   1567 						} else {
   1568 							Changed = 0;
   1569 						}
   1570 					}
   1571 				}
   1572 				if (New_Scenario()==0) {
   1573 					CarryOverMoney = 0;
   1574 					Changed = 1;
   1575 				}
   1576 				process = false;
   1577 				break;
   1578 
   1579 			/*
   1580 			.......................... Load scenario ...........................
   1581 			*/
   1582 			case 1:
   1583 				if (Changed) {
   1584 					rc = CCMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
   1585 					HiddenPage.Clear();
   1586 					Flag_To_Redraw(true);
   1587 					Render();
   1588 					if (rc==0) {
   1589 						if (Save_Scenario()!=0) {
   1590 							break;
   1591 						} else {
   1592 							Changed = 0;
   1593 						}
   1594 					}
   1595 				}
   1596 				if (Load_Scenario()==0) {
   1597 					CarryOverMoney = 0;
   1598 					Changed = 0;
   1599 				}
   1600 				process = false;
   1601 				break;
   1602 
   1603 			/*
   1604 			.......................... Save scenario ...........................
   1605 			*/
   1606 			case 2:
   1607 				if (Save_Scenario() == 0) {
   1608 					Changed = 0;
   1609 				}
   1610 				process = false;
   1611 				break;
   1612 
   1613 			/*
   1614 			.......................... Edit map size ...........................
   1615 			*/
   1616 			case 3:
   1617 				if (Size_Map(MapCellX, MapCellY, MapCellWidth, MapCellHeight)==0) {
   1618 					process = false;
   1619 					Changed = 1;
   1620 				}
   1621 				break;
   1622 
   1623 			/*
   1624 			.......................... Add an object ...........................
   1625 			*/
   1626 			case 4:
   1627 				if (Placement_Dialog() == 0) {
   1628 					Start_Placement();
   1629 					process = false;
   1630 				}
   1631 				break;
   1632 
   1633 			/*
   1634 			......................... Scenario options .........................
   1635 			*/
   1636 			case 5:
   1637 				if (Scenario_Dialog() == 0) {
   1638 					Changed = 1;
   1639 					process = false;
   1640 				}
   1641 				break;
   1642 
   1643 			/*
   1644 			.......................... Other options ...........................
   1645 			*/
   1646 			case 6:
   1647 				AI_Menu();
   1648 				process = false;
   1649 				break;
   1650 
   1651 			/*
   1652 			...................... Test-drive this scenario ....................
   1653 			*/
   1654 			case 7:
   1655 				if (Changed) {
   1656 					rc = CCMessageBox().Process("Save Changes?", TXT_YES, TXT_NO);
   1657 					HiddenPage.Clear();
   1658 					Flag_To_Redraw(true);
   1659 					Render();
   1660 					if (rc==0) {
   1661 						if (Save_Scenario()!=0) {
   1662 							break;
   1663 						} else {
   1664 							Changed = 0;
   1665 						}
   1666 					}
   1667 				}
   1668 				Changed = 0;
   1669 				Debug_Map = false;
   1670 				Start_Scenario(ScenarioName);
   1671 				return;
   1672 		}
   1673 	}
   1674 
   1675 	/*------------------------------------------------------------------------
   1676 	Restore the display:
   1677 	- Clear HIDPAGE to erase any spurious drawing done by the menu system
   1678 	- Invoke Flag_To_Redraw to tell DisplayClass to re-render the whole screen
   1679 	- Invoke Redraw() to update the display
   1680 	------------------------------------------------------------------------*/
   1681 	HiddenPage.Clear();
   1682 	Flag_To_Redraw(true);
   1683 	Render();
   1684 }
   1685 
   1686 
   1687 /***************************************************************************
   1688  * MapEditClass::AI_Menu -- menu of AI options                             *
   1689  *                                                                         *
   1690  * INPUT:                                                                  *
   1691  *                                                                         *
   1692  * OUTPUT:                                                                 *
   1693  *                                                                         *
   1694  * WARNINGS:                                                               *
   1695  *                                                                         *
   1696  * HISTORY:                                                                *
   1697  *   11/29/1994 BR : Created.                                              *
   1698  *=========================================================================*/
   1699 void MapEditClass::AI_Menu(void)
   1700 {
   1701 	int selection;						// option the user picks
   1702 	bool process;						// menu stays up while true
   1703 	char const *_menus[MAX_AI_MENU_NUM + 1];
   1704 
   1705 	/*
   1706 	-------------------------- Fill in menu strings --------------------------
   1707 	*/
   1708 	_menus[0] = "Pre-Build a Base";
   1709 	_menus[1] = "Import Triggers";
   1710 	_menus[2] = "Edit Triggers";
   1711 	_menus[3] = "Import Teams";
   1712 	_menus[4] = "Edit Teams";
   1713 	_menus[5] = NULL;
   1714 
   1715 	/*
   1716 	----------------------------- Main Menu loop -----------------------------
   1717 	*/
   1718 	Override_Mouse_Shape(MOUSE_NORMAL);		// display default mouse cursor
   1719 	process = true;
   1720 	while (process) {
   1721 
   1722 		/*
   1723 		................ Invoke game callback, to update music ................
   1724 		*/
   1725 		Call_Back();
   1726 
   1727 		/*
   1728 		............................. Invoke menu .............................
   1729 		*/
   1730 		Hide_Mouse();		// Do_Menu assumes the mouse is already hidden
   1731 		selection = Do_Menu(&_menus[0], true);
   1732 		Show_Mouse();
   1733 		if (UnknownKey==KN_ESC || UnknownKey==KN_LMOUSE || UnknownKey==KN_RMOUSE) {
   1734 			break;
   1735 		}
   1736 
   1737 		/*
   1738 		.......................... Process selection ..........................
   1739 		*/
   1740 		switch (selection) {
   1741 			/*
   1742 			......................... Pre-Build a Base .........................
   1743 			*/
   1744 			case 0:
   1745 				Start_Base_Building();
   1746 				process = false;
   1747 				break;
   1748 
   1749 			/*
   1750 			......................... Import Triggers ..........................
   1751 			*/
   1752 			case 1:
   1753 				if (Import_Triggers()==0)
   1754 					process = false;
   1755 				break;
   1756 
   1757 			/*
   1758 			......................... Trigger Editing ..........................
   1759 			*/
   1760 			case 2:
   1761 				Handle_Triggers();
   1762 				/*
   1763 				................ Go into trigger placement mode .................
   1764 				*/
   1765 				if (CurTrigger) {
   1766 					Start_Trigger_Placement();
   1767 				}
   1768 				process = false;
   1769 				break;
   1770 
   1771 			/*
   1772 			........................... Import Teams ...........................
   1773 			*/
   1774 			case 3:
   1775 				if (Import_Teams()==0)
   1776 					process = false;
   1777 				break;
   1778 
   1779 			/*
   1780 			........................... Team Editing ...........................
   1781 			*/
   1782 			case 4:
   1783 				Handle_Teams("Teams");
   1784 				process = false;
   1785 				break;
   1786 		}
   1787 	}
   1788 }
   1789 
   1790 
   1791 /***************************************************************************
   1792  * MapEditClass::Verify_House -- is this objtype ownable by this house?    *
   1793  *                                                                         *
   1794  * INPUT:                                                                  *
   1795  *      house         house to check                                       *
   1796  *      objtype      ObjectTypeClass to check                              *
   1797  *                                                                         *
   1798  * OUTPUT:                                                                 *
   1799  *      0 = isn't ownable, 1 = it is                                       *
   1800  *                                                                         *
   1801  * WARNINGS:                                                               *
   1802  *      none.                                                              *
   1803  *                                                                         *
   1804  * HISTORY:                                                                *
   1805  *   11/16/1994 BR : Created.                                              *
   1806  *=========================================================================*/
   1807 bool MapEditClass::Verify_House(HousesType house, ObjectTypeClass const *objtype)
   1808 {
   1809 	/*
   1810 	--------------- Verify that new house can own this object ----------------
   1811 	*/
   1812 	return((objtype->Get_Ownable() & (1 << house)) != 0);
   1813 }
   1814 
   1815 
   1816 /***************************************************************************
   1817  * MapEditClass::Cycle_House -- finds next valid house for object type     *
   1818  *                                                                         *
   1819  * INPUT:                                                                  *
   1820  *      objtype      ObjectTypeClass ptr to get house for                  *
   1821  *      curhouse      current house value to start with                    *
   1822  *                                                                         *
   1823  * OUTPUT:                                                                 *
   1824  *      HousesType that's valid for this object type                       *
   1825  *                                                                         *
   1826  * WARNINGS:                                                               *
   1827  *      none.                                                              *
   1828  *                                                                         *
   1829  * HISTORY:                                                                *
   1830  *   11/23/1994 BR : Created.                                              *
   1831  *=========================================================================*/
   1832 HousesType MapEditClass::Cycle_House(HousesType curhouse,
   1833 	ObjectTypeClass const *objtype)
   1834 {
   1835 	HousesType count;			// prevents an infinite loop
   1836 
   1837 	/*------------------------------------------------------------------------
   1838 	Loop through all house types, starting with the one after 'curhouse';
   1839 	return the first one that's valid
   1840 	------------------------------------------------------------------------*/
   1841 	count = HOUSE_NONE;
   1842 	while (1) {
   1843 
   1844 		/*
   1845 		.......................... Go to next house ...........................
   1846 		*/
   1847 		curhouse++;
   1848 		if (curhouse == HOUSE_COUNT) {
   1849 			curhouse = HOUSE_FIRST;
   1850 		}
   1851 
   1852 		/*
   1853 		................ Count # iterations; don't go forever .................
   1854 		*/
   1855 		count++;
   1856 		if (count == HOUSE_COUNT) {
   1857 			curhouse = HOUSE_NONE;
   1858 			break;
   1859 		}
   1860 
   1861 		/*
   1862 		................... Break if this is a valid house ....................
   1863 		*/
   1864 		if (HouseClass::As_Pointer(curhouse) && Verify_House(curhouse,objtype)) {
   1865 			break;
   1866 		}
   1867 	}
   1868 
   1869 	return(curhouse);
   1870 }
   1871 
   1872 
   1873 /***************************************************************************
   1874  * MapEditClass::Fatal -- exits with error message                         *
   1875  *                                                                         *
   1876  * INPUT:                                                                  *
   1877  *      code      tells which message to display; this minimizes the       *
   1878  *               use of character strings in the code.                     *
   1879  *                                                                         *
   1880  * OUTPUT:                                                                 *
   1881  *      none.                                                              *
   1882  *                                                                         *
   1883  * WARNINGS:                                                               *
   1884  *      none.                                                              *
   1885  *                                                                         *
   1886  * HISTORY:                                                                *
   1887  *   12/12/1994 BR : Created.                                              *
   1888  *=========================================================================*/
   1889 void MapEditClass::Fatal(int txt)
   1890 {
   1891 	Prog_End();
   1892 	printf("%s\n",txt);
   1893 	if (!RunningAsDLL) {
   1894 		exit(EXIT_FAILURE);
   1895 	}
   1896 }
   1897 
   1898 
   1899 bool MapEditClass::Scroll_Map(DirType facing, int & distance, bool really)
   1900 {
   1901 	if (Debug_Map) {
   1902 		/*
   1903 		** The popup gadgets require the entire map to be redrawn if we scroll.
   1904 		*/
   1905 		if (really) {
   1906 			Flag_To_Redraw(true);
   1907 		}
   1908 	}
   1909 	return(MouseClass::Scroll_Map(facing, distance, really));
   1910 }
   1911 
   1912 
   1913 void MapEditClass::Detach(ObjectClass * object)
   1914 {
   1915 	if (GrabbedObject == object) {
   1916 		GrabbedObject = 0;
   1917 	}
   1918 }
   1919 
   1920 
   1921 #endif
   1922 
   1923 #include	"mapedsel.cpp"