/* $Id: copy_paste.cpp 5998 2006-05-28 07:45:14Z Frostregen $ */

#include "stdafx.h"
#include "openttd.h"
#include "table/sprites.h"
#include "strings_type.h"
#include "table/strings.h"
#include "clear_func.h"
#include "company_func.h"
#include "tile_type.h"
#include "window_type.h"
#include "gui.h"
#include "rail_map.h"
#include "rail_gui.h"
#include "gfx_func.h"
#include "settings_type.h"
#include "sound_type.h"
#include "sound_func.h"
#include "command_type.h"
#include "command_func.h"
#include "tunnel_map.h"
#include "bridge_map.h"
#include "tunnelbridge_map.h"
#include "tunnelbridge.h"
#include "waypoint_base.h"
#include "debug.h"
#include "depot_map.h"
#include "saveload/saveload.h"
#include "window_func.h"
#include "strings_func.h"
#include "slope_type.h"
#include "network/network.h"
#include "command_queue.h"
#include "copy_paste.h"
#include "core/alloc_func.hpp"
#include "core/endian_func.hpp"

/* Total Space used = 8 * COPY_MAX = ?kb */
CopyPaste _copy_paste = CopyPaste();

/* Major version for saved templates */
extern const uint32 COPYPASTE_VERSION = 1;

CopyPasteCommandQueue _copy_paste_command_queue = CopyPasteCommandQueue();

StringID error_message;		///< error string, used by save/load
StringID error_extra;		///< extra error message (or NULL)

CopyPaste::CopyPaste()
{
	m_width     = 0;
	m_height    = 0;
	
	m_copy_with_rail          = true;
	m_copy_with_road          = true;
	m_copy_with_other         = false;
	m_paste_vacant_terrain    = 1;
	m_convert_rail            = true;
	m_clear_before_build      = true;
	m_toggle_signal_direction = false;
}

void CopyPaste::AllocateMapArray(uint32 max_tiles)
{
	this->ClearCopyArrays();
	m_heightmap      = CallocT< int8>(max_tiles);
	m_terrain_needed = CallocT<uint8>(max_tiles);
	m_tiletype       = CallocT<uint8>(max_tiles);
	m_railroad       = CallocT<uint8>(max_tiles);
	m_signals        = CallocT<uint16>(max_tiles);
}

CopyPaste::~CopyPaste()
{
	this->ClearCopyArrays();
}

/** Returns if something is currently copied 
 */
bool CopyPaste::IsSomethingCopied()
{
	return !((GetWidth() == 0) || (GetHeight() == 0));
}

/** Clears the Arrays which store the copied area.
 */
void CopyPaste::ClearCopyArrays()
{
	free(m_heightmap);
	free(m_terrain_needed);
	free(m_tiletype);
	free(m_railroad);
	free(m_signals);
	m_width = 0;
	m_height = 0;
}


/**
 * SaveLoad function for templates
 * TODO: Compression
 * TODO: Better error handling (use goto for block error handling)
 **/
SaveOrLoadResult CopyPaste::SaveLoadTemplate(const char *filename, int mode)
{
	FILE* fh;
	uint32 hdr[4];
	uint32 tlen = GetWidth() * GetHeight();
	uint32 blen = (GetWidth() - 1) * (GetHeight() - 1);
	uint32 index;
	uint16 tmp16;
	uint16* ptmp16;
	ptmp16 = &tmp16;
	
	uint32 version;

	fh = (mode == SL_SAVE) ? fopen(filename, "wb") : fopen(filename, "rb");

	switch(mode) {
		case SL_SAVE:
			hdr[0] = TO_BE32X('TMPL');
			/* For now we only have a major version, but may use minor in future? */
			hdr[1] = TO_BE32(COPYPASTE_VERSION);
			hdr[2] = TO_BE32(GetWidth());
			hdr[3] = TO_BE32(GetHeight());

			if (fwrite(hdr, sizeof(hdr), 1, fh) != 1) {
				fclose(fh);
				SetError(STR_TEMPLATE_SAVE_FAILED, STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
				return SL_ERROR;
			}

			if (fwrite(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto save_error;
			if (fwrite(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto save_error;
			if (fwrite(m_tiletype, sizeof(uint8), blen, fh) != blen) goto save_error;
			if (fwrite(m_railroad, sizeof(uint8), blen, fh) != blen) goto save_error;

			for (index = 0; index < blen; index++)
			{
				tmp16 = TO_BE16(m_signals[index]);
				if (fwrite(ptmp16, sizeof(uint16), 1, fh) != 1) goto save_error;
			}

			break;

		case SL_LOAD:
			if (fread(hdr, sizeof(hdr), 1, fh) != 1) goto load_error;
			if (FROM_BE32(hdr[0]) != 'TMPL') {
				SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN);
				return SL_ERROR;
			}

			version = FROM_BE32(hdr[1]);
			DEBUG(sl, 1, "Loading template with version %d", version);

			/* Check whether we can load this template */
			if (version > COPYPASTE_VERSION) {
				DEBUG(sl, 1, "Can't load template with version %d, too new!", version);
				SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW);
				return SL_ERROR;
			}
	DEBUG(sl, 1, "Getting bounds");

			{
				uint32 width = FROM_BE32(hdr[2]);
				uint32 height = FROM_BE32(hdr[3]);
				AllocateMapArray(width * height);
				SetWidth(width);
				SetHeight(height);
			}

			tlen = GetWidth() * GetHeight();
			blen = (GetWidth() - 1) * (GetHeight() - 1);

	DEBUG(sl, 1, "Allocated arrays, loading from file");

			if (fread(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto load_error;
			if (fread(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto load_error;
			if (fread(m_tiletype, sizeof(uint8), blen, fh) != blen) goto load_error;
			if (fread(m_railroad, sizeof(uint8), blen, fh) != blen) goto load_error;
	DEBUG(sl, 1, "Reading signals");

			for (index = 0; index < blen; index++) {
				if (fread(ptmp16, sizeof(uint16), 1, fh) != 1) goto load_error;
				m_signals[index] = FROM_BE16(tmp16);
			}
			SetWindowDirty(WC_COPY_PASTE, 0);
			break;

		default:
			/* Not reached */
			break;
	}

	fclose(fh);

	return SL_OK;

save_error:
	SetError(STR_TEMPLATE_SAVE_FAILED);
	fclose(fh);
	return SL_ERROR;

load_error:
	SetError(STR_TEMPLATE_LOAD_FAILED);
	fclose(fh);
	return SL_ERROR;
}

/** Set the error string & an extra message */
void CopyPaste::SetError(StringID message, StringID extra)
{
	error_message = message;
	error_extra = extra;
}

/** Get the string representation of the error message */
const char* CopyPaste::GetErrorString()
{
	//SetDParam(0, error_message);
	SetDParam(0, error_extra);

	static char str[512];
	GetString(str, error_message, lastof(str));
	return str;
}

/** DoCommand for Copy&Paste.
 * If shift is pressed, a cost-estimate is displayed instead of executing the paste.
 * 
 * If we are in multiplayer the pasting is redirected to the command-queue,
 * which delays execution, to prevent overflowing the network connection.
 */
void CopyPaste::CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
{
	if (_shift_pressed) {
		CommandCost res = DoCommand(tile, p1, p2, DC_QUERY_COST, cmd & 0xFF, "");
		if (!res.Failed())
			m_costs.AddCost(res);
	}
	else {
#ifdef ENABLE_NETWORK
		if (_networking) {
			_copy_paste_command_queue.CopyPasteQueueCommand(tile, p1, p2, callback, cmd);
		}
		else
#endif /* ENABLE_NETWORK */
			DoCommandP(tile, p1, p2, cmd, callback);
	}
}

/* *** Copy&Paste Helper functions. Mainly the same as the originals. Just without sound *** */

/**
 * @param tile The Tile to operate on 
 * @param mode true means Raise, false means Lower
 */
void CopyPaste::CP_RaiseLowerLand(TileIndex tile, int mode)
{
	CP_DoCommand(tile, 8, (uint32)mode, NULL, CMD_TERRAFORM_LAND | CMD_MSG(mode ? STR_ERROR_CAN_T_RAISE_LAND_HERE : STR_ERROR_CAN_T_LOWER_LAND_HERE));
}

void CopyPaste::CP_PlaceRail(TileIndex tile, int cmd, uint32 railtype)
{
	CP_DoCommand(tile, railtype, cmd, NULL,
		CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)
	);
}

void CopyPaste::CP_PlaceSignals(TileIndex tile, Track track, SignalType type, uint direction, bool semaphore)
{
	if (IsPbsSignal(type) && direction > 0) direction--;
	CP_DoCommand(tile, track | (semaphore ? 1 : 0) << 4 | type << 5 | direction << 15, 0, NULL,
			CMD_BUILD_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE));
}

void CopyPaste::CP_PlaceRoad(TileIndex tile, uint8 road_bits)
{
	CP_DoCommand(tile, road_bits, 0, NULL, CMD_BUILD_ROAD | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
}

void CopyPaste::CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through)
{
	CP_DoCommand(tile, direction, truck_stop | drive_through << 1 | roadtype << 2 | INVALID_STATION << 16, NULL, CMD_BUILD_ROAD_STOP | CMD_MSG(truck_stop ? STR_ERROR_CAN_T_BUILD_TRUCK_STATION : STR_ERROR_CAN_T_BUILD_BUS_STATION));
}

void CopyPaste::CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype)
{
	CP_DoCommand(tile, railtype, 0, NULL,
		CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
}

void CopyPaste::CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype)
{
	CP_DoCommand(tile, 0x200 | roadtype, 0, NULL, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
}

void CopyPaste::CP_Build_Bridge(TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type)
{
	CP_DoCommand(end, start,
		bridgetype | (rail_road_type << 8) | (transport_type << 15), NULL,
		CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE));
}

void CopyPaste::CP_PlaceRail_Depot(TileIndex tile, uint8 railtype, uint8 direction)
{
	CP_DoCommand(tile, railtype, direction, NULL,
		CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT));
}

void CopyPaste::CP_PlaceRoad_Depot(TileIndex tile, uint8 direction_type)
{
	CP_DoCommand(tile, direction_type, 0, NULL,
		CMD_BUILD_ROAD_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
}

void CopyPaste::CP_PlaceWaypoint(TileIndex tile, uint8 waypoint_type)
{
	CP_DoCommand(tile, waypoint_type, 0, NULL, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT));
}

void CopyPaste::CP_ClearTile(TileIndex start_tile, TileIndex end_tile)
{
	CP_DoCommand(start_tile, end_tile, 0, NULL, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA));
}

uint8 CopyPaste::MirrorSignalDirection(uint8 direction)
{
	if (direction == 0) return direction;
	return (direction == 1 ? 2 : 1);
}

DisallowedRoadDirections CopyPaste::MirrorOneWayRoadDirection(DisallowedRoadDirections drd)
{
	if (drd == DRD_NONE || drd == DRD_BOTH) return drd;
	return drd == DRD_SOUTHBOUND ? DRD_NORTHBOUND : DRD_SOUTHBOUND;
}

void CopyPaste::SwapSignalInfo(uint index)
{
	uint16 signal = m_signals[index];
	/* Clear bit 2-16 */
	for (uint i = 2; i < 16; i++)
		ClrBit(m_signals[index], i);
	/* Set bit 2 to former 3 */
	SB(m_signals[index], 2, 1, GB(signal, 3, 1));
	/* Set bit 3 to former 2 */
	SB(m_signals[index], 3, 1, GB(signal, 2, 1));
	/* Set bit 6+7 to former 8+9 */
	SB(m_signals[index], 6, 2, MirrorSignalDirection(GB(signal, 8, 2)));
	/* Set bit 8+9 to former 6+7 */
	SB(m_signals[index], 8, 2, MirrorSignalDirection(GB(signal, 6, 2)));
	/* Exchange signal types too */
	/* Set bit 10-12 to former 13-15 */
	SB(m_signals[index], 10, 3, GB(signal, 13, 3));
	/* Set bit 13-15 to former 10-12 */
	SB(m_signals[index], 13, 3, GB(signal, 10, 3));
}

/** This function pastes landscape */
void CopyPaste::PasteLandscape(TileIndex tile)
{
	TileIndex sx = TileX(tile);
	TileIndex sy = TileY(tile);
	uint size_x = GetWidth();
	uint size_y = GetHeight();
	int8 count, h_diff;
	uint h_tile;

	TileIndex index;
	/* Base height level is from upper right tile. */
	uint baseh = TileHeight(tile);
	/* Bulldoze tiles which will be built on */
	if (m_clear_before_build) {
		index = 0;
		TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {

			if (GetCPTileType(index) != CP_TILE_CLEAR) {
				CP_ClearTile(tile, tile);
			}
			index++;

		}
	}

	/* Check if we want to restore any terrain at all */
	if (m_paste_vacant_terrain > 0) {
		/* Restore terrain 
		 * Please look into "CopyArea" for details on which bit is used for which information
		 */
		index = 0;
		TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {

			if (HasBit(m_terrain_needed[index], 0) || (m_paste_vacant_terrain == 2)) {

				/* Do special heightlevel calculations if we are networking,
				 * since we cannot measure the heightlevel if we delay the execution.
				 * Lowering/Raising land affects neighbour tiles too...
				 * Else we just use the current tileheight we get from the map.
				 */
#ifdef ENABLE_NETWORK
				if (_networking) {
					h_tile = TileHeight(tile);
					if ((cur_h != size_y) && (cur_w != size_x)) {
						/* Look NE and NW */
						h_tile = ClampToRight(index, baseh, h_tile);
						h_tile = ClampToUp(index, baseh, h_tile, size_x);
						/* use clamped height instead of actual height */
						h_diff = GetHeight(baseh, index) - h_tile;
					}
					else {
						if ((cur_h == size_y) && (cur_w == size_x)) {
							/* First Tile is always at baseh */
							h_diff = GetHeight(baseh, index) - TileHeight(tile);
						}
						else if (cur_w == size_x) {
							/* Right Border, clamp to upper tile only */
							h_tile = ClampToUp(index, baseh, h_tile, size_x);
							h_diff = GetHeight(baseh, index) - h_tile;
						}
						else {
							/* Upper Border, clamp to right tile only */
							h_tile = ClampToRight(index, baseh, h_tile);
							h_diff = GetHeight(baseh, index) - h_tile;
						}
					}
				}
				else
#endif /* ENABLE_NETWORK */
					h_diff = GetHeight(baseh, index) - TileHeight(tile);

				/* Now raise/lower the tile according to our calculations */
				if (h_diff > 0)	{
					for (count = 0; count < h_diff; count++)
						CP_RaiseLowerLand(tile, 1);
				}
				else if (h_diff < 0) {
					for (count = h_diff; count < 0; count++)
						CP_RaiseLowerLand(tile, 0);
				}
			}
			index++;

		}
	}

}

/** This function pastes signals for a given index */
void CopyPaste::PasteSignals(uint index, TileIndex tile)
{
	uint16 signal = m_signals[index];
	if (m_toggle_signal_direction) {
		SB(signal, 6, 2, MirrorSignalDirection(GB(signal, 6, 2)));
		SB(signal, 8, 2, MirrorSignalDirection(GB(signal, 8, 2)));
	}
	bool firstrun = true;
	for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
		if (m_railroad[index] & TrackToTrackBits(t)) {
			if (((IsDiagonalTrack(t) || t == TRACK_LEFT || t == TRACK_UPPER) &&
				HasBit(signal, 0)) ||
				((t == TRACK_RIGHT || t == TRACK_LOWER) && HasBit(signal, 1))) {
				CP_PlaceSignals(tile, t, 
					(SignalType)GB(signal, firstrun ? 10 : 13, 3),
					GB(signal, firstrun ? 6 : 8, 2),
					HasBit(signal, firstrun ? 2 : 3));
					firstrun = false;
			}
		}
	}
}

/** This function calculates the height,
 * the given tile will have, after the neighbour(right) tile is restored.
 * In OTTD adjacent tiles may only differ in height by 1 level.
 */
int8 CopyPaste::ClampToRight(TileIndex index, int8 baseh, int8 h_tile)
{
	int8 h_right = GetHeight(baseh, index - 1);

	if (h_tile > (h_right + 1)) {
		h_tile = h_right + 1;
	}
	else if (h_tile < (h_right - 1)) {
		h_tile = h_right - 1;
	}

	return h_tile;
}

/** This function calculates the height,
 * the given tile will have, after the neighbour(upper) tile is restored.
 * In OTTD adjacent tiles may only differ in height by 1 level.
 */
int8 CopyPaste::ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x)
{
	int8 h_up = GetHeight(baseh, index - size_x);

	if (h_tile > (h_up + 1)) {
		h_tile = h_up + 1;
	}
	else if (h_tile < (h_up - 1)) {
		h_tile = h_up - 1;
	}

	return h_tile;
}

/** Game command which pastes the copied content.
 * The result depends on setting some variables:
 * m_paste_vacant_terrain, m_convert_rail, m_clear_before_build and m_toggle_signal_direction
 * @param tile upper right corner to paste to
 */
void CopyPaste::internal_PasteArea(TileIndex tile)
{
	int8 baseh;
	TileIndex index = 0;
	int32 size_x, size_y;
	bool success = true;
	TileIndex sx = TileX(tile);
	TileIndex sy = TileY(tile);
	TileIndex ex = sx + GetWidth();
	TileIndex ey = sy + GetHeight();

	/* Reset paste costs */
	if (_shift_pressed) {
		m_costs.MultiplyCost(0);
	}

	/* Nothing copied? exit... */
	if (! IsSomethingCopied()) return;
	
	/* Paste out of map? exit... */
	if ((ex >= MapSizeX()) || (ey >= MapSizeY())) return;

	size_x = GetWidth();
	size_y = GetHeight();

	/* Base height level is from upper right tile. */
	baseh = (int8)TileHeight(tile);
	
	/* Restore the landscape */
	PasteLandscape(tile);
	
	/* Paste Rail, Depot, Tunnel, Road, Bridge: 
	 * Please look into "CopyArea" for details on which bit is used for which information
	 */
	index = 0;
	TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
	
		uint minortt = GetCPMinorTileType(index);

		switch(GetCPTileType(index)) {
			case CP_TILE_RAIL: {
				uint rt = GB(m_railroad[index], 6, 2); //railtype
				switch (minortt) {
					case RAIL_TILE_NORMAL:
					case RAIL_TILE_SIGNALS:
//					case RAIL_TILE_WAYPOINT:
						for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
							if (m_railroad[index] & TrackToTrackBits(t)) CP_PlaceRail(tile, t, m_convert_rail ? (uint)_cur_railtype : rt);
						}
						break;

					case RAIL_TILE_DEPOT:
						CP_PlaceRail_Depot(tile, m_convert_rail ? (uint)_cur_railtype : rt, GB(m_railroad[index], 0, 2));
						break;
				}
			} break;
			case CP_TILE_ROAD: {
				switch(minortt) {
					case ROAD_TILE_CROSSING:
						CP_PlaceRail(tile, GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_Y : TRACK_X, m_convert_rail ? (uint)_cur_railtype : GB(m_signals[index], 4, 2));
					/* fallthrough */
					case ROAD_TILE_NORMAL:
						if (GB(m_railroad[index], 0, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 0, 4) | (ROADTYPE_ROAD << 4) | (minortt == ROAD_TILE_NORMAL ? (GB(m_signals[index], 0, 2) << 6) : 0));
						if (GB(m_railroad[index], 4, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 4, 4) | (ROADTYPE_TRAM << 4));
						break;
					case ROAD_TILE_DEPOT:
						CP_PlaceRoad_Depot(tile, GB(m_railroad[index], 0, 2) | HasBit(m_railroad[index], 2) << 2);
						break;
				}
			} break;
			case CP_TILE_STATION: 
				switch(minortt) {
					case CP_TILE_ROAD:
						CP_PlaceRoadStop(tile, GB(m_railroad[index], 0, 2), GB(m_railroad[index], 6, 2), HasBit(m_railroad[index], 2), HasBit(m_railroad[index], 3));
				}


			case CP_TILE_TUNNELBRIDGE:
				if (HasBit(minortt, 0)) {
					/* Tunnels: 
					* TODO: check if tunnel end will be at right place (=inside area)
					* Same check as bridge? move into tunneldir, until tunneltile reached
					*/
					if (HasBit(m_railroad[index], 4)) {
						if (GB(m_railroad[index], 2, 2) == TRANSPORT_ROAD) {
							CP_PlaceRoad_Tunnel(tile, GB(m_railroad[index], 6, 2));
						} else {
							CP_PlaceRail_Tunnel(tile, m_convert_rail ? (uint) _cur_railtype : GB(m_railroad[index], 6, 2));
						}
					}
				} else if (HasBit(m_railroad[index], 4)) {
					/* Bridges: */
					/* If we get here, there is a bridge start here. Now find the bridge end 
					 * TODO Shorten code by setting up variables inside switch statement, and use them inside one loop at the end
					 */
					bool bridge_error = false;
					TileIndex tmp_tile = tile;
					uint rdd = ReverseDiagDir((DiagDirection)GB(m_railroad[index], 0, 2));
					bool found = false;
					TileIndex i;
					switch (GB(m_railroad[index], 0, 2)) {
						case DIAGDIR_NE:
							/* -X */
							i = 1;
							while ((TileX(tile) - i) >= sx) {
								if (GetCPTileType(index - i) == CP_TILE_TUNNELBRIDGE && 
									!HasBit(GetCPMinorTileType(index - i), 0) &&
									!HasBit(m_railroad[index - i], 4) &&
									GB(m_railroad[index - i], 0, 2) == rdd) {
									found = true;
									break;
								}
								i++;
							}
							if ((TileX(tile) - i) < sx || !found)
								bridge_error = true;
							else
								tmp_tile += TileDiffXY(0 - i, 0);
							break;
						case DIAGDIR_SW:
							/* +X */
							i = 1;
							while ((TileX(tile) + i) < (sx + size_x - 1)) {
								if (GetCPTileType(index + i) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + i), 0) && !HasBit(m_railroad[index + i], 4) && GB(m_railroad[index + i], 0, 2) == rdd) {
									found = true;
									break;
								}
								i++;
							}
							if ((TileX(tile) + i) >= (sx + size_x - 1) || !found)
								bridge_error = true;
							else
								tmp_tile += TileDiffXY(+i, 0);
							break;
						case DIAGDIR_SE:
							/* +Y */
							i = 1;
							while ((TileY(tile) + i) < (sy + size_y - 1)) {
								if (GetCPTileType(index + (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index + (i * (size_x - 1))), 0) && !HasBit(m_railroad[index + (i * (size_x - 1))], 4) && GB(m_railroad[index + (i * (size_x - 1))], 0, 2) == rdd) {
									found = true;
									break;
								}
								i++;
							}
							if ((TileY(tile) + i) >= (sy + size_y - 1) || !found)
								bridge_error = true;
							else
								tmp_tile += TileDiffXY(0, +i);
							break;
						case DIAGDIR_NW:
							/* -Y */
							i = 1;
							while ((TileY(tile) + i) >= (sy + size_y - 1)) {
								if (GetCPTileType(index - (i * (size_x - 1))) == CP_TILE_TUNNELBRIDGE && !HasBit(GetCPMinorTileType(index - (i * (size_x - 1))), 0) && !HasBit(m_railroad[index - (i * (size_x - 1))], 4) && GB(m_railroad[index - (i * (size_x - 1))], 0, 2) == rdd) {
									found = true;
									break;
								}
								i++;
							}
							if ((TileY(tile) - i) < sy || !found)
								bridge_error = true;
							else
								tmp_tile += TileDiffXY(0, 0 - i);
							break;
					}
					if (!bridge_error) {
						if (GB(m_railroad[index], 2, 2) == TRANSPORT_RAIL) {
							CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_RAIL, m_convert_rail ? (uint) _cur_railtype : ((m_railroad[index] >> 6) & 3U) );
						} else {
							CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_ROAD, ((m_railroad[index] >> 6) & 3U) );
						}
					}
				}
				break;
			default: break;
		}

		index++;

	}

	/* Restore Signals and Waypoints (separated because they depend on underlying track) */
	index = 0;
	TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
		if (GetCPTileType(index) == CP_TILE_RAIL) {
			switch(GetCPMinorTileType(index)) {
/*				case RAIL_TILE_WAYPOINT:
					CP_PlaceWaypoint(tile, GB(m_signals[index], 0, 8));
					break;*/
				case RAIL_TILE_SIGNALS:
					PasteSignals(index, tile);
			}
		}
		index++;
	}


	/* If shift is pressed, show the cost estimate. Else play a sound on success */
	if (_shift_pressed) {
		ShowEstimatedCostOrIncome(m_costs.GetCost(), 100, 100);
	}
	else {
		if (success) SndPlayTileFx(SND_1F_SPLAT, tile);
	}
}

/**
 * Safe Paste Command. 
 * Checks CopyPasteCommandQueue-Size in network games
 **/
void CopyPaste::PasteArea(TileIndex tile)
{
	if (_settings_client.gui.cp_paste_speed != 0xFF) {
		this->internal_PasteArea(tile);
	}
	else {
		ShowErrorMessage(STR_COPY_PASTE_PASTE_DISABLED, INVALID_STRING_ID, WL_ERROR, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
	}
}

/**
 * Indicates this tile needs to be terraformed, in order to restore some building.
 * Bit 0 indicates this tile is needed for terraforming,
 * but is not directly build on.
 * Bit 1 indicates this tile is beeing built on.
 **/
void CopyPaste::TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex)
{
	/* always restore terrain on this tiles */
	SetBit(m_terrain_needed[tindex], 0);
	SetBit(m_terrain_needed[tindex + 1], 0);
	SetBit(m_terrain_needed[tindex + GetWidth()], 0);
	SetBit(m_terrain_needed[tindex + GetWidth() + 1], 0);
}

/**
 * Game command which copies a selected area
 **/
void CopyPaste::CopyArea(TileIndex end, TileIndex start)
{
	int8 baseh;
	TileIndex tindex = 0;
	TileIndex bindex = 0;
	int size_x, size_y;
	bool success = false;
	TileIndex sx = TileX(start);
	TileIndex sy = TileY(start);
	TileIndex ex = TileX(end);
	TileIndex ey = TileY(end);
	bool tunnelbridge_error;
	int32 maxdiff, i;


	if (ex < sx) Swap(ex, sx);
	if (ey < sy) Swap(ey, sy);
	/* add one tile, but just for heightmap */
	ex++;
	ey++;
	size_x = (ex - sx) + 1;
	size_y = (ey - sy) + 1;

	this->AllocateMapArray(size_x * size_y);
	SetWidth(size_x);
	SetHeight(size_y);

	/* Create a command DIFF to a flat Area */
	/* Base level is from first tile. */
	baseh = (int8)TileHeight(TileXY(sx, sy));
	tindex = 0;
	TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {

		m_heightmap[tindex] = ((int8)TileHeight(tile)) - baseh;
		tindex++;

		/* Dont Copy tracks/buildings on last x/y row */
		if (cur_h == 1 || cur_w == 1) {
			success = true;
			continue;
		}

		/* Copy building/track here */
		switch (GetTileType(tile)) {
			case MP_RAILWAY:
				/* Check if we want to copy this type of building */
				if (!m_copy_with_rail) break;
				if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
				SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
				SB(m_tiletype[bindex], 4, 4, GetRailTileType(tile));
				TerrainNeededAroundTile(tindex - 1, bindex);
				
				/* Store Railway type in bits 6+7 */
				SB(m_railroad[bindex], 6, 2, GetRailType(tile));
				
				switch (GetRailTileType(tile)) {
					case RAIL_TILE_DEPOT:
						/* Depot here */
						/* store direction: bit 2+3 */
						SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_RAIL));
						break;
/*					case RAIL_TILE_WAYPOINT:
						// Waypoint here
						// Store Waypoint custom gfx id
						SB(m_signals[bindex], 0, 8, GetWaypointByTile(tile)->stat_id);
						// Store axis
						SB(m_railroad[bindex], 0, 2, AxisToTrackBits(GetWaypointAxis(tile)));
						break;*/
					case RAIL_TILE_SIGNALS: {
						/* Signals: */
						/* Store Signal:
						 * Bit      0 : signal 1 present
						 * Bit      1 : signal 2 present
						 * Bit      2 : variant S1
						 * Bit      3 : variant S2
						 * Bits: 6- 7 : Direction S1 (Clicks to build)
						 * Bits: 8- 9 : Direction S2 (Clicks to build)
						 * Bits: 10-12: signal type S1
						 * Bits: 13-15: signal type S2
						 */
						bool first_run = true;
						for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
							if (HasTrack(tile, t) && HasSignalOnTrack(tile, t)) {
								if (t == TRACK_X || t == TRACK_Y || t == TRACK_LEFT || t == TRACK_UPPER) {
									SetBit(m_signals[bindex], 0);
								} else {
									SetBit(m_signals[bindex], 1);
								}
								/* Store signal direction */
								Trackdir td = TrackToTrackdir(t);
								if (!(HasSignalOnTrackdir(tile, td) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)))) {
									/* one way signal, not 2-way */
									if (t == TRACK_LEFT || t == TRACK_RIGHT) td = ReverseTrackdir(td);
									SB(m_signals[bindex], first_run ? 6 : 8, 2, HasSignalOnTrackdir(tile, td) ? 1 : 2);
								}
								/* Bit 2/3: signal variant(semaphore/electric) ToDo: find some place this can live with another one */
								SB(m_signals[bindex], first_run ? 2 : 3, 1, GetSignalVariant(tile, t));
								/* Bits 10 - 12/13-15: signal type */
								SB(m_signals[bindex], first_run ? 10 : 13, 3, GetSignalType(tile, t));
								first_run = false;
							}
						}
					}
					/* fallthrough */
					case RAIL_TILE_NORMAL:
						/* Store Railway tracks in bits 0 to 5: */
						m_railroad[bindex] |= GetTrackBits(tile);
						break;
				}

				break;
			case MP_ROAD:
				if (GetRoadTileType(tile) != ROAD_TILE_CROSSING && (!m_copy_with_road || !(m_copy_with_other || IsTileOwner(tile, _current_company)))) break;
				SB(m_tiletype[bindex], 0, 4, CP_TILE_ROAD);
				SB(m_tiletype[bindex], 4, 4, GetRoadTileType(tile));
				switch (GetRoadTileType(tile)) {
					case ROAD_TILE_CROSSING: {
						/* Crossing: Get Axis, store railtype too 
						 * TODO Unify...
						 */
						RoadBits roadbits = GetCrossingRoadBits(tile);
						Track railtrack = GetCrossingRailTrack(tile);
						bool should_copy_rail = m_copy_with_rail && (m_copy_with_other || IsTileOwner(tile, _current_company));
						bool should_copy_road = m_copy_with_road;
						if (should_copy_rail && !should_copy_road) {
							SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
							SB(m_tiletype[bindex], 4, 4, RAIL_TILE_NORMAL);
							TerrainNeededAroundTile(tindex - 1, bindex);
							/* Copy the rail */
							m_railroad[bindex] |= TrackToTrackBits(railtrack);
							SB(m_railroad[bindex], 6, 2, GetRailType(tile));
						}
						if (should_copy_road && !should_copy_rail) {
							SB(m_tiletype[bindex], 4, 4, ROAD_TILE_NORMAL);
						}
						if (should_copy_road && should_copy_rail) {
							SB(m_signals[bindex], 4, 2, GetRailType(tile));
						}
						if (should_copy_road) {
							/* Copy the road */
							for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
								if ((m_copy_with_other || GetRoadOwner(tile, rt) == _current_company) && GetRoadTypes(tile) & RoadTypeToRoadTypes(rt)) {
									TerrainNeededAroundTile(tindex - 1, bindex);
									SB(m_railroad[bindex], rt * 4, 4, roadbits);
								}
							}
						}
						if (!should_copy_road && !should_copy_rail) {
							SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
						}
						} break;

					case ROAD_TILE_DEPOT:
						/* Direction: bit 0+1 */
						SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_ROAD));
						/* Tram or Road? bit 2 */
						if (GetRoadTypes(tile) != ROADTYPES_ROAD) SetBit(m_railroad[bindex], 2);
						TerrainNeededAroundTile(tindex - 1, bindex);
						break;

					case ROAD_TILE_NORMAL:
						for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
							SB(m_railroad[bindex], rt * 4, 4, GetRoadBits(tile, rt));
						}
						TerrainNeededAroundTile(tindex - 1, bindex);
						SB(m_signals[bindex], 0, 2, GetDisallowedRoadDirections(tile));
						break;
				}
				break;

			case MP_STATION:
				/* Stations: currently partially supported */
				SB(m_tiletype[bindex], 0, 4, CP_TILE_STATION);

			
				switch (GetStationType(tile)) {
					/* Road stations */
					case STATION_TRUCK:
					case STATION_BUS:
						SB(m_tiletype[bindex], 4, 4, CP_TILE_ROAD);

						SB(m_railroad[bindex], 0, 2, GetRoadStopDir(tile));
						if(GetStationType(tile) == STATION_TRUCK) SetBit(m_railroad[bindex], 2);
						SB(m_railroad[bindex], 3, 1, IsDriveThroughStopTile(tile));
						SB(m_railroad[bindex], 6, 2, GetRoadTypes(tile));
						break;					
	
					/* Rail stations */
					case STATION_RAIL:
						SB(m_tiletype[bindex], 4, 4, CP_TILE_RAIL);

						//GetStationSpec for newgrf info
						break;

					default:
						/* Not reached */
						break;

				}
				break;

			case MP_TUNNELBRIDGE:
				/* Check for tunnel or bridge 
				 * TODO Try to unify bridges an tunnels, since error checking(start/endtile) is essentially the same
				 */
				if (IsTunnelTile(tile)) {
					/* Storing Tunnel */
					if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
					if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
					if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
					tunnelbridge_error = false;
					if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
						int tilediff = 1;
						/* Store tunnel direction in bit 0-1 */
						SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
						/* Store tunnel transport type in bit 2-3 */
						SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
						/* Store tunnel start in bit 4 */
						SetBit(m_railroad[bindex], 4);
						/* Store rail type too, if it is a railtunnel */
						if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
							m_railroad[bindex] |= (GetRailType(tile) << 6);
						if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
							m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
						/* Now mark all tiles between tunnel start and end as needed 
						 * TODO Unify... ;)
						 */
						switch (GetTunnelBridgeDirection(tile)) {
							case DIAGDIR_SW:
								maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
								if (maxdiff <= 0) {
									tunnelbridge_error = true;
									break;
								}
								while ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
									tilediff++;
								}
								if ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) || (tilediff > maxdiff))
									tunnelbridge_error = true;
								if (!tunnelbridge_error) {
									/* Mark Tiles as needed: */
									for (i = 0; i <= tilediff; i++)
										TerrainNeededAroundTile(tindex - 1 + i, bindex + i);

									/* Set other TunnelEnd */
									SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
									SB(m_tiletype[bindex + tilediff], 4, 1, true);
									/* Store tunnel direction in bit 1-2 */
									m_railroad[bindex + tilediff] |= GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0));
									/* Store tunnel transport type in bit 3 */
									SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
									/* Store tunnel start in bit 4 (No, this is tunnel End) */
									/* Store rail type too, if railtunnel */
									if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
										m_railroad[bindex + tilediff] = (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
								}
								break;
							case DIAGDIR_SE:
								maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
								if (maxdiff <= 0) {
									tunnelbridge_error = true;
									break;
								}
								while ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
									tilediff++;
								}
								if ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) || (tilediff > maxdiff))
									tunnelbridge_error = true;
								if (!tunnelbridge_error) {
									/* Mark Tiles as needed: */
									for (i = 0; i <= tilediff; i++)
										TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));

									/* Set other TunnelEnd */
									SB(m_tiletype[bindex + tilediff * (size_x - 1)], 0, 4, CP_TILE_TUNNELBRIDGE);
									SB(m_tiletype[bindex + tilediff * (size_x - 1)], 4, 1, true);
									/* Store tunnel direction in bit 0-1 */
									m_railroad[bindex + (tilediff * (size_x - 1))] |= GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff));
									/* Store tunnel transport type in bit 3 */
									SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
									/* Store tunnel start in bit 4 (No, this is tunnel End) */
									/* Store rail type too, if railtunnel */
									if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
										m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
								}
								break;
							default:
							break;
						}
						if (tunnelbridge_error) {
							/* ResetBridge on Error */
							m_railroad[bindex] = 0;
						} else {
							SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
							SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
						}
					}
					else {
						/* Other directions: do nothing since we have everything copied already */
					}
				}
				else {
					/* Store bridge (Has to be in "else", since Tunnel is a "BridgeRamp" too) */
					if (IsBridge(tile)) {
						if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
						if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
						if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;

						tunnelbridge_error = false;
						if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
							int tilediff = 1;
							/* Direction bit 0-1 */
							SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
							/* TransportType bit 3 */
							SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
							/* Store "IsBridge-Start" in Bit4 */
							SetBit(m_railroad[bindex], 4);
							/* BridgeType in m_signals */
							m_signals[bindex] = GetBridgeType(tile);
							/* Store Railtype */
							if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
								m_railroad[bindex] |= (GetRailType(tile) << 6);
							if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
								m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
							/* Now mark all tiles between bridge start and end as needed 
							 * TODO: Unify :)
							 */
							switch (GetTunnelBridgeDirection(tile)) {
								TileIndex otherEnd;
								case DIAGDIR_SW:
									maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
									if (maxdiff <= 0) {
										tunnelbridge_error = true;
										break;
									}
									otherEnd = GetOtherBridgeEnd(tile);
									tilediff = DistanceManhattan(tile, otherEnd);
									if (tilediff > maxdiff)
										tunnelbridge_error = true;
									
									if (!tunnelbridge_error) {
										/* Mark Tiles as needed: */
										for (i = 0; i <= tilediff; i++)
											TerrainNeededAroundTile(tindex - 1 + i, bindex + i);

										/* Set other BridgeEnd */
										SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
										SB(m_tiletype[bindex + tilediff], 4, 1, IsTunnelTile(tile));
										/* Direction bit 0-1 */
										SB(m_railroad[bindex + tilediff], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0)));
										/* TransportType bit 3 */
										SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
										/* Store "IsBridge-Start" in Bit4 (Nope, this is the Bridge-End) */
										
										/* BridgeType in m_signals */
										m_signals[bindex + tilediff] = GetBridgeType(tile + TileDiffXY(tilediff, 0));
										/* Store Railtype */
										if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
											m_railroad[bindex + tilediff] |= (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
									}
									break;
								case DIAGDIR_SE:
									maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
									if (maxdiff <= 0) {
										tunnelbridge_error = true;
										break;
									}
									otherEnd = GetOtherBridgeEnd(tile);
									tilediff = DistanceManhattan(tile, otherEnd);
									if (tilediff > maxdiff)
										tunnelbridge_error = true;
									if (!tunnelbridge_error) {
										/* Mark Tiles as needed: */
										for (i = 0; i <= tilediff; i++)
											TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));

										/* Set other BridgeEnd */
										SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 0, 4, CP_TILE_TUNNELBRIDGE);
										SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 4, 1, IsTunnelTile(tile));
										/* Direction bit 0-1 */
										SB(m_railroad[bindex + tilediff * (size_x - 1)], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff)));
										/* TransportType bit 3 */
										SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
										/* Store "IsBridge-Start" in Bit4 (Nope, this is the End) */
										/* BridgeType  in m_signals */
										m_signals[bindex + tilediff * (size_x - 1)] = GetBridgeType(tile + TileDiffXY(0, tilediff));
										/* Store Railtype */
										if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
											m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
									}
									break;
								default:
									break;
							}
							if (tunnelbridge_error) {
								/* ResetBridge on Error */
								m_railroad[bindex] = 0;
								m_signals[bindex] = 0;
							} else {
								SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
								SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
							}
						}
						else {
							/* Other directions, do nothing, since we have copied everything already */
						}
					}
				}
				break;

			default:
				SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
				/* Storing nothing */
				break;
		}
		bindex++;
		success = true;

	}

	if (success) SndPlayTileFx(SND_1F_SPLAT, end);
}

/* Get the height of a tile */
uint CopyPaste::GetHeight(uint baseh, uint index)
{
	return baseh + m_heightmap[index];
}

Slope CopyPaste::GetSlope(uint index)
{
	int a = m_heightmap[index];
	int min = a;
	int b = m_heightmap[index + 1];
	if (min > b) min = b;
	int c = m_heightmap[index + GetWidth()];
	if (min > c) min = c;
	int d = m_heightmap[index + GetWidth() + 1];
	if (min > d) min = d;
	
	uint r = SLOPE_FLAT;
	
	if (a -= min != 0) r += (--a << 4) + SLOPE_N;
	if (c -= min != 0) r += (--c << 4) + SLOPE_E;
	if (d -= min != 0) r += (--d << 4) + SLOPE_S;
	if (b -= min != 0) r += (--b << 4) + SLOPE_W;
	
	return (Slope)r;
}

TrackBits CopyPaste::GetCPTrackBits(uint index)
{
	if (GetCPTileType(index) == CP_TILE_RAIL) {
		if (GetCPMinorTileType(index) != RAIL_TILE_DEPOT) return (TrackBits)GB(m_railroad[index], 0, 6);
	} else if (GetCPTileType(index) == CP_TILE_ROAD) {
		if (GetCPMinorTileType(index) == ROAD_TILE_CROSSING) return GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_BIT_Y : TRACK_BIT_X;
	}
	return TRACK_BIT_NONE;
}

/** Get the major tiletype of a tile*/
CopyPaste::CopyPasteTileType CopyPaste::GetCPTileType(uint index)
{
	return (CopyPasteTileType)GB(m_tiletype[index], 0, 4);
}

/** Get the minor tiletype of a tile*/
uint CopyPaste::GetCPMinorTileType(uint index)
{
	return GB(m_tiletype[index], 4, 4);
}
/**
 * Rotate an array.
 * @param dir 1: rotate CW
 *            -1: rotate CCW
 **/
template <typename T> 
static void rotate(T* b, int w, int h, int dir)
{
	int i, len, x, y, src, target;

	/* Allocate a temporary array */
	len = w * h;
	T* tmp = MallocT<T>(len);

	/* Copy array to new allocated array: */
	for (i = 0; i < len; i++)
		tmp[i] = b[i];

	/* Copy rotated values back to original array */
	if (dir == 1) {
		for (y = 0; y < h; y++) {
			for (x = 0; x < w; x++) {
				/*X index is now the old Y index
				 * Y index is w - x
				 */
				src = (y * w) + x;
				target = (((w - 1) - x) * h) + y;
				b[target] = tmp[src];
			}
		}
	}
	else if (dir == -1) {
			/* Copy rotated values back to original array */
			for (y = 0; y < h; y++) {
				for (x = 0; x < w; x++) {
					/* X index is now the old Y index
					 * Y index is w - x
					 */
					src = (y * w) + x;
					target = (x * h) + (h - 1 - y);
					b[target] = tmp[src];
				}
			}
	}

	/* Release temp array */
	free(tmp);
}

/**
 * Mirror array.
 * @param axis 0: horizontal
 *              1: vertical
 **/
template <typename T>
static void mirror(T* b, int w, int h, Axis axis)
{
	int x, y;


	switch (axis) {
		case AXIS_X:
			for (y = 0; y < h; y++) {
				for (x = 0; x < (w / 2); x++) {
					Swap<T>(b[x + (y * w)], b[(w - x - 1) + (y * w)]);
				}
			}
		break;
		case AXIS_Y:
			for (y = 0; y < (h / 2); y++) {
				for (x = 0; x < w; x++) {
					Swap<T>(b[x + (y * w)], b[ x + ((h - y - 1) * w)]);
				}
			}
		break;
		default: NOT_REACHED();
	}
}

/**
 * Rotates the copied content ClockWise
 * This is done by first rotating the array indices,
 * then rotating the field contents
 **/
void CopyPaste::RotateSelectionCW()
{
	int w = GetWidth() - 1;
	int h = GetHeight() - 1;
	uint8 storelocation;
	int index, len;

	uint8 tmp8;
	uint16 tmp16;

	/* Rotate array indices */
	rotate(m_heightmap, GetWidth(), GetHeight(), 1);
	rotate(m_terrain_needed, GetWidth(), GetHeight(), 1);
	rotate(m_tiletype, w, h, 1);
	rotate(m_railroad,   w, h, 1);
	rotate(m_signals,w, h, 1);

	/* Rotate array content (tracks, depots etc..) */
	len = w * h;
	for (index = 0; index < len; index++) {

		switch (GetCPTileType(index)) {
			case CP_TILE_RAIL:
				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
					/* Depot */
					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
					break;
				}
				/* Rotate Tracks */
				/* Copy tracks to temp variable */
				tmp8 = m_railroad[index];
				/* Clear Tracks: bits 0-5 */
				m_railroad[index] &= ~((1 << 6) - 1);
				/* Copy back + rotate 
				 * TODO exchange with arithmetic or lookup-table version...shorten...
				 */
				if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_X;
				if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_Y;
				if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
				
				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
					/* Signals */
					/* copy original signals to temporary variable */
					tmp16 = m_signals[index];
					/* Clear Signals: Bits 0-2 */
					ClrBit(m_signals[index], 0);
					ClrBit(m_signals[index], 1);
					/* Copy back + rotate position */
					storelocation = 6;
					/* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
					if ((m_railroad[index] & TRACK_BIT_Y) && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
					}
					if ((m_railroad[index] & TRACK_BIT_X) && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
					}
					if ((m_railroad[index] & TRACK_BIT_RIGHT) && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 1);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
					if ((m_railroad[index] & TRACK_BIT_LEFT) && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 0);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						if (storelocation == 8) {
							/* Exchange Storelocations */
							SwapSignalInfo(index);
						}
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
					}
					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 1);
					}
				
				}
				break;
				
			case CP_TILE_ROAD:
				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
					/* Depot */
					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
					break;
				}

				/* rotate one-way roads */
				if (m_railroad[index] & ROAD_Y && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
				}
				/* Road: */
				SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90RIGHT));
				/* Trams: */
				SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90RIGHT));

			
				break;

				case CP_TILE_TUNNELBRIDGE:
					/* tunnel/bridge */
					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
				
					break;

				default: break;
		}

	}

	Swap(this->m_width, this->m_height);
}

/**
 * Rotates the copied content CounterClockWise
 * This is done by first rotating the array indices,
 * then rotating the field contents
 **/
void CopyPaste::RotateSelectionCCW()
{
	int w = GetWidth() - 1;
	int h = GetHeight() - 1;
	uint8 storelocation;
	int index, len;

	uint8 tmp8;
	uint16 tmp16;

	/* Rotate array indices */
	rotate(m_heightmap, GetWidth(), GetHeight(), -1);
	rotate(m_terrain_needed, GetWidth(), GetHeight(), -1);
	rotate(m_tiletype, w, h, -1);
	rotate(m_railroad,   w, h, -1);
	rotate(m_signals,w, h, -1);

	/* Rotate array content (tracks, depots etc..) */
	len = w * h;
	for (index = 0; index < len; index++) {
		switch (GetCPTileType(index)) {
			case CP_TILE_RAIL:
				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
					//Depot
					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
					break;
				}
				tmp8 = m_railroad[index];
				/* Clear Tracks: bits 0-5 */
				m_railroad[index] &= ~63U;
				/* Copy back + rotate */
				if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_X;
				if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_Y;
				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
				if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
					//Signals
					//Rotate position
					tmp16 = m_signals[index];
					/* Clear Signals: Bits 0-2 */
					ClrBit(m_signals[index], 0);
					ClrBit(m_signals[index], 1);
					//Copy back + rotate position
					storelocation = 6;
					/* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
					if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
					}
					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
					}
					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 1);
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 1);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 0);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						if (storelocation == 8) {
							/* Exchange Storelocations */
							SwapSignalInfo(index);
						}
						storelocation = 8;
					}
				}
				break;

			case CP_TILE_ROAD:
				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
					//Depot
					SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
					break;
				}
				if (m_railroad[index] & ROAD_X && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
				}
				//Road & Tram:
				SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90LEFT));
				SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90LEFT));

				break;

			case CP_TILE_TUNNELBRIDGE:
				SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
				break;
			default: break;
		}

	}

	Swap(this->m_height, this->m_width);
}

void CopyPaste::MirrorSelectionHorizontal()
{
	int w = GetWidth() - 1;
	int h = GetHeight() - 1;
	uint8 storelocation;
	int index, len;

	uint8 tmp8;
	uint16 tmp16;

	/* Mirror array indices */
	mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_X);
	mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_X);
	mirror(m_tiletype, w, h, AXIS_X);
	mirror(m_railroad,   w, h, AXIS_X);
	mirror(m_signals,w, h, AXIS_X);

	/* Mirror array content (left <-> right) */
	len = w * h;
	for (index = 0; index < len; index++) {
		switch (GetCPTileType(index)) {
			case CP_TILE_RAIL:
				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
					//Depot
					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
					if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
					SB(m_railroad[index], 0, 2, tmp8); // set
					break;
				}
				tmp8 = m_railroad[index];
				/* Clear Tracks: Bits 0-5 */
				m_railroad[index] &= ~63U;
				/* Copy back + mirror */
				if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_X;
				if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_Y;
				if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
				
				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
					//Signals
					//Mirror position
					tmp16 = m_signals[index];
					//Copy back + mirror position
					storelocation = 6;
					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
					}
					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
						storelocation = 8;
					}
				}
				break;

			case CP_TILE_ROAD:
				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
					//Depot
					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
					if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
					SB(m_railroad[index], 0, 2, tmp8); // set
					break;
				}
				//Road:
				//swap horizontal roadpieces
				tmp8 = m_railroad[index];
				m_railroad[index] &= ~(ROAD_NE | ROAD_SW  | ((ROAD_NE | ROAD_SW) << 4)); //Clear specific road bits
				if ((tmp8 & ROAD_NE) > 0) m_railroad[index] |= ROAD_SW;
				if ((tmp8 & ROAD_SW) > 0) m_railroad[index] |= ROAD_NE;
				if ((tmp8 & (ROAD_NE << 4)) > 0) m_railroad[index] |= (ROAD_SW << 4);
				if ((tmp8 & (ROAD_SW << 4)) > 0) m_railroad[index] |= (ROAD_NE << 4);
				
				if ((tmp8 & ROAD_X) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
				}
				
				break;

			case CP_TILE_TUNNELBRIDGE:
				/* Tunnel/Bridge
				 * just mirror direction
				 */
				tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 001
				if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
				SB(m_railroad[index], 0, 2, tmp8); // set
			
				break;

			default: break;
		}

	}
}

void CopyPaste::MirrorSelectionVertical()
{
	int w = GetWidth() - 1;
	int h = GetHeight() - 1;
	uint8 storelocation;
	int index, len;

	uint8 tmp8;
	uint16 tmp16;

	//Mirror arrays
	mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_Y);
	mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_Y);
	mirror(m_tiletype, w, h, AXIS_Y);
	mirror(m_railroad,   w, h, AXIS_Y);
	mirror(m_signals,w, h, AXIS_Y);

	//Mirror array content (up <-> down)
	len = w * h;
	for (index = 0; index < len; index++) {
		switch (GetCPTileType(index)) {
			case CP_TILE_RAIL:
				if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
					//Depot
					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
					if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
					SB(m_railroad[index], 0, 2, tmp8); // set
					break;
				}
				tmp8 = m_railroad[index];
				//Clear Tracks
				m_railroad[index] &= ~63U; //Clear bits 0-5
				//Copy back + mirror
				if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_X;
				if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_Y;
				if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
				if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
				if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
				if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
				if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
					//Signals
					//Mirror position
					tmp16 = m_signals[index];
					//Clear Signals
					ClrBit(m_signals[index], 0);
					ClrBit(m_signals[index], 1);
					//Copy back + mirror position
					storelocation = 6;
					if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
					}
					if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 0);
						SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
					}
					if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 1);
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 0);
						if (storelocation == 8) {
							/* Exchange Storelocations */
							SwapSignalInfo(index);
						}
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
						SetBit(m_signals[index], 1);
						storelocation = 8;
					}
					if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
						SetBit(m_signals[index], 0);
						if (storelocation == 8) {
							/* Exchange Storelocations */
							SwapSignalInfo(index);
						}
						storelocation = 8;
					}

				}
				break;

			case CP_TILE_ROAD:
				if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
					//Depot
					tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
					if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
					SB(m_railroad[index], 0, 2, tmp8); // set
					break;
				}
				//Road:
				//swap horizontal roadpieces
				tmp8 = m_railroad[index];
				m_railroad[index] &= ~(ROAD_NW | ROAD_SE  | ((ROAD_NW | ROAD_SE) << 4)); //Clear specific road bits
				if ((tmp8 & ROAD_NW) > 0) m_railroad[index] |= ROAD_SE;
				if ((tmp8 & ROAD_SE) > 0) m_railroad[index] |= ROAD_NW;
				if ((tmp8 & (ROAD_NW << 4)) > 0) m_railroad[index] |= (ROAD_SE << 4);
				if ((tmp8 & (ROAD_SE << 4)) > 0) m_railroad[index] |= (ROAD_NW << 4);
				
				if ((tmp8 & ROAD_Y) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
					SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
				}
				
				break;

			case CP_TILE_TUNNELBRIDGE:
				/* Tunnel / Bridge */
				tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 1-2
				if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
				SB(m_railroad[index], 0, 2, tmp8); // set
				break;
			default: break;
		}

	}
}


