copy_paste.cpp

00001 /* $Id: copy_paste.cpp 5998 2006-05-28 07:45:14Z Frostregen $ */
00002 
00003 #include "stdafx.h"
00004 #include "openttd.h"
00005 #include "table/sprites.h"
00006 #include "strings_type.h"
00007 #include "table/strings.h"
00008 #include "clear_func.h"
00009 #include "company_func.h"
00010 #include "tile_type.h"
00011 #include "window_type.h"
00012 #include "gui.h"
00013 #include "rail_map.h"
00014 #include "rail_gui.h"
00015 #include "gfx_func.h"
00016 #include "settings_type.h"
00017 #include "sound_type.h"
00018 #include "sound_func.h"
00019 #include "command_type.h"
00020 #include "command_func.h"
00021 #include "tunnel_map.h"
00022 #include "bridge_map.h"
00023 #include "tunnelbridge_map.h"
00024 #include "tunnelbridge.h"
00025 #include "waypoint_base.h"
00026 #include "debug.h"
00027 #include "depot_map.h"
00028 #include "saveload/saveload.h"
00029 #include "window_func.h"
00030 #include "strings_func.h"
00031 #include "slope_type.h"
00032 #include "network/network.h"
00033 #include "command_queue.h"
00034 #include "copy_paste.h"
00035 #include "core/alloc_func.hpp"
00036 #include "core/endian_func.hpp"
00037 
00038 /* Total Space used = 8 * COPY_MAX = ?kb */
00039 CopyPaste _copy_paste = CopyPaste();
00040 
00041 /* Major version for saved templates */
00042 extern const uint32 COPYPASTE_VERSION = 1;
00043 
00044 CopyPasteCommandQueue _copy_paste_command_queue = CopyPasteCommandQueue();
00045 
00046 StringID error_message;   
00047 StringID error_extra;   
00048 
00049 CopyPaste::CopyPaste()
00050 {
00051   m_width     = 0;
00052   m_height    = 0;
00053   
00054   m_copy_with_rail          = true;
00055   m_copy_with_road          = true;
00056   m_copy_with_other         = false;
00057   m_paste_vacant_terrain    = 1;
00058   m_convert_rail            = true;
00059   m_clear_before_build      = true;
00060   m_toggle_signal_direction = false;
00061 }
00062 
00063 void CopyPaste::AllocateMapArray(uint32 max_tiles)
00064 {
00065   this->ClearCopyArrays();
00066   m_heightmap      = CallocT< int8>(max_tiles);
00067   m_terrain_needed = CallocT<uint8>(max_tiles);
00068   m_tiletype       = CallocT<uint8>(max_tiles);
00069   m_railroad       = CallocT<uint8>(max_tiles);
00070   m_signals        = CallocT<uint16>(max_tiles);
00071 }
00072 
00073 CopyPaste::~CopyPaste()
00074 {
00075   this->ClearCopyArrays();
00076 }
00077 
00080 bool CopyPaste::IsSomethingCopied()
00081 {
00082   return !((GetWidth() == 0) || (GetHeight() == 0));
00083 }
00084 
00087 void CopyPaste::ClearCopyArrays()
00088 {
00089   free(m_heightmap);
00090   free(m_terrain_needed);
00091   free(m_tiletype);
00092   free(m_railroad);
00093   free(m_signals);
00094   m_width = 0;
00095   m_height = 0;
00096 }
00097 
00098 
00104 SaveOrLoadResult CopyPaste::SaveLoadTemplate(const char *filename, int mode)
00105 {
00106   FILE* fh;
00107   uint32 hdr[4];
00108   uint32 tlen = GetWidth() * GetHeight();
00109   uint32 blen = (GetWidth() - 1) * (GetHeight() - 1);
00110   uint32 index;
00111   uint16 tmp16;
00112   uint16* ptmp16;
00113   ptmp16 = &tmp16;
00114   
00115   uint32 version;
00116 
00117   fh = (mode == SL_SAVE) ? fopen(filename, "wb") : fopen(filename, "rb");
00118 
00119   switch(mode) {
00120     case SL_SAVE:
00121       hdr[0] = TO_BE32X('TMPL');
00122       /* For now we only have a major version, but may use minor in future? */
00123       hdr[1] = TO_BE32(COPYPASTE_VERSION);
00124       hdr[2] = TO_BE32(GetWidth());
00125       hdr[3] = TO_BE32(GetHeight());
00126 
00127       if (fwrite(hdr, sizeof(hdr), 1, fh) != 1) {
00128         fclose(fh);
00129         SetError(STR_TEMPLATE_SAVE_FAILED, STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
00130         return SL_ERROR;
00131       }
00132 
00133       if (fwrite(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto save_error;
00134       if (fwrite(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto save_error;
00135       if (fwrite(m_tiletype, sizeof(uint8), blen, fh) != blen) goto save_error;
00136       if (fwrite(m_railroad, sizeof(uint8), blen, fh) != blen) goto save_error;
00137 
00138       for (index = 0; index < blen; index++)
00139       {
00140         tmp16 = TO_BE16(m_signals[index]);
00141         if (fwrite(ptmp16, sizeof(uint16), 1, fh) != 1) goto save_error;
00142       }
00143 
00144       break;
00145 
00146     case SL_LOAD:
00147       if (fread(hdr, sizeof(hdr), 1, fh) != 1) goto load_error;
00148       if (FROM_BE32(hdr[0]) != 'TMPL') {
00149         SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_BROKEN);
00150         return SL_ERROR;
00151       }
00152 
00153       version = FROM_BE32(hdr[1]);
00154       DEBUG(sl, 1, "Loading template with version %d", version);
00155 
00156       /* Check whether we can load this template */
00157       if (version > COPYPASTE_VERSION) {
00158         DEBUG(sl, 1, "Can't load template with version %d, too new!", version);
00159         SetError(STR_TEMPLATE_LOAD_FAILED, STR_GAME_SAVELOAD_ERROR_TEMPLATE_TOO_NEW);
00160         return SL_ERROR;
00161       }
00162   DEBUG(sl, 1, "Getting bounds");
00163 
00164       {
00165         uint32 width = FROM_BE32(hdr[2]);
00166         uint32 height = FROM_BE32(hdr[3]);
00167         AllocateMapArray(width * height);
00168         SetWidth(width);
00169         SetHeight(height);
00170       }
00171 
00172       tlen = GetWidth() * GetHeight();
00173       blen = (GetWidth() - 1) * (GetHeight() - 1);
00174 
00175   DEBUG(sl, 1, "Allocated arrays, loading from file");
00176 
00177       if (fread(m_heightmap, sizeof(int8), tlen, fh) != tlen) goto load_error;
00178       if (fread(m_terrain_needed, sizeof(uint8), tlen, fh) != tlen) goto load_error;
00179       if (fread(m_tiletype, sizeof(uint8), blen, fh) != blen) goto load_error;
00180       if (fread(m_railroad, sizeof(uint8), blen, fh) != blen) goto load_error;
00181   DEBUG(sl, 1, "Reading signals");
00182 
00183       for (index = 0; index < blen; index++) {
00184         if (fread(ptmp16, sizeof(uint16), 1, fh) != 1) goto load_error;
00185         m_signals[index] = FROM_BE16(tmp16);
00186       }
00187       SetWindowDirty(WC_COPY_PASTE, 0);
00188       break;
00189 
00190     default:
00191       /* Not reached */
00192       break;
00193   }
00194 
00195   fclose(fh);
00196 
00197   return SL_OK;
00198 
00199 save_error:
00200   SetError(STR_TEMPLATE_SAVE_FAILED);
00201   fclose(fh);
00202   return SL_ERROR;
00203 
00204 load_error:
00205   SetError(STR_TEMPLATE_LOAD_FAILED);
00206   fclose(fh);
00207   return SL_ERROR;
00208 }
00209 
00211 void CopyPaste::SetError(StringID message, StringID extra)
00212 {
00213   error_message = message;
00214   error_extra = extra;
00215 }
00216 
00218 const char* CopyPaste::GetErrorString()
00219 {
00220   //SetDParam(0, error_message);
00221   SetDParam(0, error_extra);
00222 
00223   static char str[512];
00224   GetString(str, error_message, lastof(str));
00225   return str;
00226 }
00227 
00234 void CopyPaste::CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
00235 {
00236   if (_shift_pressed) {
00237     CommandCost res = DoCommand(tile, p1, p2, DC_QUERY_COST, cmd & 0xFF, "");
00238     if (!res.Failed())
00239       m_costs.AddCost(res);
00240   }
00241   else {
00242 #ifdef ENABLE_NETWORK
00243     if (_networking) {
00244       _copy_paste_command_queue.CopyPasteQueueCommand(tile, p1, p2, callback, cmd);
00245     }
00246     else
00247 #endif /* ENABLE_NETWORK */
00248       DoCommandP(tile, p1, p2, cmd, callback);
00249   }
00250 }
00251 
00252 /* *** Copy&Paste Helper functions. Mainly the same as the originals. Just without sound *** */
00253 
00258 void CopyPaste::CP_RaiseLowerLand(TileIndex tile, int mode)
00259 {
00260   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));
00261 }
00262 
00263 void CopyPaste::CP_PlaceRail(TileIndex tile, int cmd, uint32 railtype)
00264 {
00265   CP_DoCommand(tile, railtype, cmd, NULL,
00266     CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)
00267   );
00268 }
00269 
00270 void CopyPaste::CP_PlaceSignals(TileIndex tile, Track track, SignalType type, uint direction, bool semaphore)
00271 {
00272   if (IsPbsSignal(type) && direction > 0) direction--;
00273   CP_DoCommand(tile, track | (semaphore ? 1 : 0) << 4 | type << 5 | direction << 15, 0, NULL,
00274       CMD_BUILD_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE));
00275 }
00276 
00277 void CopyPaste::CP_PlaceRoad(TileIndex tile, uint8 road_bits)
00278 {
00279   CP_DoCommand(tile, road_bits, 0, NULL, CMD_BUILD_ROAD | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
00280 }
00281 
00282 void CopyPaste::CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through)
00283 {
00284   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));
00285 }
00286 
00287 void CopyPaste::CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype)
00288 {
00289   CP_DoCommand(tile, railtype, 0, NULL,
00290     CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
00291 }
00292 
00293 void CopyPaste::CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype)
00294 {
00295   CP_DoCommand(tile, 0x200 | roadtype, 0, NULL, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE));
00296 }
00297 
00298 void CopyPaste::CP_Build_Bridge(TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type)
00299 {
00300   CP_DoCommand(end, start,
00301     bridgetype | (rail_road_type << 8) | (transport_type << 15), NULL,
00302     CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE));
00303 }
00304 
00305 void CopyPaste::CP_PlaceRail_Depot(TileIndex tile, uint8 railtype, uint8 direction)
00306 {
00307   CP_DoCommand(tile, railtype, direction, NULL,
00308     CMD_BUILD_TRAIN_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT));
00309 }
00310 
00311 void CopyPaste::CP_PlaceRoad_Depot(TileIndex tile, uint8 direction_type)
00312 {
00313   CP_DoCommand(tile, direction_type, 0, NULL,
00314     CMD_BUILD_ROAD_DEPOT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_HERE));
00315 }
00316 
00317 void CopyPaste::CP_PlaceWaypoint(TileIndex tile, uint8 waypoint_type)
00318 {
00319   CP_DoCommand(tile, waypoint_type, 0, NULL, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT));
00320 }
00321 
00322 void CopyPaste::CP_ClearTile(TileIndex start_tile, TileIndex end_tile)
00323 {
00324   CP_DoCommand(start_tile, end_tile, 0, NULL, CMD_CLEAR_AREA | CMD_MSG(STR_ERROR_CAN_T_CLEAR_THIS_AREA));
00325 }
00326 
00327 uint8 CopyPaste::MirrorSignalDirection(uint8 direction)
00328 {
00329   if (direction == 0) return direction;
00330   return (direction == 1 ? 2 : 1);
00331 }
00332 
00333 DisallowedRoadDirections CopyPaste::MirrorOneWayRoadDirection(DisallowedRoadDirections drd)
00334 {
00335   if (drd == DRD_NONE || drd == DRD_BOTH) return drd;
00336   return drd == DRD_SOUTHBOUND ? DRD_NORTHBOUND : DRD_SOUTHBOUND;
00337 }
00338 
00339 void CopyPaste::SwapSignalInfo(uint index)
00340 {
00341   uint16 signal = m_signals[index];
00342   /* Clear bit 2-16 */
00343   for (uint i = 2; i < 16; i++)
00344     ClrBit(m_signals[index], i);
00345   /* Set bit 2 to former 3 */
00346   SB(m_signals[index], 2, 1, GB(signal, 3, 1));
00347   /* Set bit 3 to former 2 */
00348   SB(m_signals[index], 3, 1, GB(signal, 2, 1));
00349   /* Set bit 6+7 to former 8+9 */
00350   SB(m_signals[index], 6, 2, MirrorSignalDirection(GB(signal, 8, 2)));
00351   /* Set bit 8+9 to former 6+7 */
00352   SB(m_signals[index], 8, 2, MirrorSignalDirection(GB(signal, 6, 2)));
00353   /* Exchange signal types too */
00354   /* Set bit 10-12 to former 13-15 */
00355   SB(m_signals[index], 10, 3, GB(signal, 13, 3));
00356   /* Set bit 13-15 to former 10-12 */
00357   SB(m_signals[index], 13, 3, GB(signal, 10, 3));
00358 }
00359 
00361 void CopyPaste::PasteLandscape(TileIndex tile)
00362 {
00363   TileIndex sx = TileX(tile);
00364   TileIndex sy = TileY(tile);
00365   uint size_x = GetWidth();
00366   uint size_y = GetHeight();
00367   int8 count, h_diff;
00368   uint h_tile;
00369 
00370   TileIndex index;
00371   /* Base height level is from upper right tile. */
00372   uint baseh = TileHeight(tile);
00373   /* Bulldoze tiles which will be built on */
00374   if (m_clear_before_build) {
00375     index = 0;
00376     TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00377 
00378       if (GetCPTileType(index) != CP_TILE_CLEAR) {
00379         CP_ClearTile(tile, tile);
00380       }
00381       index++;
00382 
00383     }
00384   }
00385 
00386   /* Check if we want to restore any terrain at all */
00387   if (m_paste_vacant_terrain > 0) {
00388     /* Restore terrain 
00389      * Please look into "CopyArea" for details on which bit is used for which information
00390      */
00391     index = 0;
00392     TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
00393 
00394       if (HasBit(m_terrain_needed[index], 0) || (m_paste_vacant_terrain == 2)) {
00395 
00396         /* Do special heightlevel calculations if we are networking,
00397          * since we cannot measure the heightlevel if we delay the execution.
00398          * Lowering/Raising land affects neighbour tiles too...
00399          * Else we just use the current tileheight we get from the map.
00400          */
00401 #ifdef ENABLE_NETWORK
00402         if (_networking) {
00403           h_tile = TileHeight(tile);
00404           if ((cur_h != size_y) && (cur_w != size_x)) {
00405             /* Look NE and NW */
00406             h_tile = ClampToRight(index, baseh, h_tile);
00407             h_tile = ClampToUp(index, baseh, h_tile, size_x);
00408             /* use clamped height instead of actual height */
00409             h_diff = GetHeight(baseh, index) - h_tile;
00410           }
00411           else {
00412             if ((cur_h == size_y) && (cur_w == size_x)) {
00413               /* First Tile is always at baseh */
00414               h_diff = GetHeight(baseh, index) - TileHeight(tile);
00415             }
00416             else if (cur_w == size_x) {
00417               /* Right Border, clamp to upper tile only */
00418               h_tile = ClampToUp(index, baseh, h_tile, size_x);
00419               h_diff = GetHeight(baseh, index) - h_tile;
00420             }
00421             else {
00422               /* Upper Border, clamp to right tile only */
00423               h_tile = ClampToRight(index, baseh, h_tile);
00424               h_diff = GetHeight(baseh, index) - h_tile;
00425             }
00426           }
00427         }
00428         else
00429 #endif /* ENABLE_NETWORK */
00430           h_diff = GetHeight(baseh, index) - TileHeight(tile);
00431 
00432         /* Now raise/lower the tile according to our calculations */
00433         if (h_diff > 0) {
00434           for (count = 0; count < h_diff; count++)
00435             CP_RaiseLowerLand(tile, 1);
00436         }
00437         else if (h_diff < 0) {
00438           for (count = h_diff; count < 0; count++)
00439             CP_RaiseLowerLand(tile, 0);
00440         }
00441       }
00442       index++;
00443 
00444     }
00445   }
00446 
00447 }
00448 
00450 void CopyPaste::PasteSignals(uint index, TileIndex tile)
00451 {
00452   uint16 signal = m_signals[index];
00453   if (m_toggle_signal_direction) {
00454     SB(signal, 6, 2, MirrorSignalDirection(GB(signal, 6, 2)));
00455     SB(signal, 8, 2, MirrorSignalDirection(GB(signal, 8, 2)));
00456   }
00457   bool firstrun = true;
00458   for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00459     if (m_railroad[index] & TrackToTrackBits(t)) {
00460       if (((IsDiagonalTrack(t) || t == TRACK_LEFT || t == TRACK_UPPER) &&
00461         HasBit(signal, 0)) ||
00462         ((t == TRACK_RIGHT || t == TRACK_LOWER) && HasBit(signal, 1))) {
00463         CP_PlaceSignals(tile, t, 
00464           (SignalType)GB(signal, firstrun ? 10 : 13, 3),
00465           GB(signal, firstrun ? 6 : 8, 2),
00466           HasBit(signal, firstrun ? 2 : 3));
00467           firstrun = false;
00468       }
00469     }
00470   }
00471 }
00472 
00477 int8 CopyPaste::ClampToRight(TileIndex index, int8 baseh, int8 h_tile)
00478 {
00479   int8 h_right = GetHeight(baseh, index - 1);
00480 
00481   if (h_tile > (h_right + 1)) {
00482     h_tile = h_right + 1;
00483   }
00484   else if (h_tile < (h_right - 1)) {
00485     h_tile = h_right - 1;
00486   }
00487 
00488   return h_tile;
00489 }
00490 
00495 int8 CopyPaste::ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x)
00496 {
00497   int8 h_up = GetHeight(baseh, index - size_x);
00498 
00499   if (h_tile > (h_up + 1)) {
00500     h_tile = h_up + 1;
00501   }
00502   else if (h_tile < (h_up - 1)) {
00503     h_tile = h_up - 1;
00504   }
00505 
00506   return h_tile;
00507 }
00508 
00514 void CopyPaste::internal_PasteArea(TileIndex tile)
00515 {
00516   int8 baseh;
00517   TileIndex index = 0;
00518   int32 size_x, size_y;
00519   bool success = true;
00520   TileIndex sx = TileX(tile);
00521   TileIndex sy = TileY(tile);
00522   TileIndex ex = sx + GetWidth();
00523   TileIndex ey = sy + GetHeight();
00524 
00525   /* Reset paste costs */
00526   if (_shift_pressed) {
00527     m_costs.MultiplyCost(0);
00528   }
00529 
00530   /* Nothing copied? exit... */
00531   if (! IsSomethingCopied()) return;
00532   
00533   /* Paste out of map? exit... */
00534   if ((ex >= MapSizeX()) || (ey >= MapSizeY())) return;
00535 
00536   size_x = GetWidth();
00537   size_y = GetHeight();
00538 
00539   /* Base height level is from upper right tile. */
00540   baseh = (int8)TileHeight(tile);
00541   
00542   /* Restore the landscape */
00543   PasteLandscape(tile);
00544   
00545   /* Paste Rail, Depot, Tunnel, Road, Bridge: 
00546    * Please look into "CopyArea" for details on which bit is used for which information
00547    */
00548   index = 0;
00549   TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00550   
00551     uint minortt = GetCPMinorTileType(index);
00552 
00553     switch(GetCPTileType(index)) {
00554       case CP_TILE_RAIL: {
00555         uint rt = GB(m_railroad[index], 6, 2); //railtype
00556         switch (minortt) {
00557           case RAIL_TILE_NORMAL:
00558           case RAIL_TILE_SIGNALS:
00559 //          case RAIL_TILE_WAYPOINT:
00560             for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00561               if (m_railroad[index] & TrackToTrackBits(t)) CP_PlaceRail(tile, t, m_convert_rail ? (uint)_cur_railtype : rt);
00562             }
00563             break;
00564 
00565           case RAIL_TILE_DEPOT:
00566             CP_PlaceRail_Depot(tile, m_convert_rail ? (uint)_cur_railtype : rt, GB(m_railroad[index], 0, 2));
00567             break;
00568         }
00569       } break;
00570       case CP_TILE_ROAD: {
00571         switch(minortt) {
00572           case ROAD_TILE_CROSSING:
00573             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));
00574           /* fallthrough */
00575           case ROAD_TILE_NORMAL:
00576             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));
00577             if (GB(m_railroad[index], 4, 4) > 0) CP_PlaceRoad(tile, GB(m_railroad[index], 4, 4) | (ROADTYPE_TRAM << 4));
00578             break;
00579           case ROAD_TILE_DEPOT:
00580             CP_PlaceRoad_Depot(tile, GB(m_railroad[index], 0, 2) | HasBit(m_railroad[index], 2) << 2);
00581             break;
00582         }
00583       } break;
00584       case CP_TILE_STATION: 
00585         switch(minortt) {
00586           case CP_TILE_ROAD:
00587             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));
00588         }
00589 
00590 
00591       case CP_TILE_TUNNELBRIDGE:
00592         if (HasBit(minortt, 0)) {
00593           /* Tunnels: 
00594           * TODO: check if tunnel end will be at right place (=inside area)
00595           * Same check as bridge? move into tunneldir, until tunneltile reached
00596           */
00597           if (HasBit(m_railroad[index], 4)) {
00598             if (GB(m_railroad[index], 2, 2) == TRANSPORT_ROAD) {
00599               CP_PlaceRoad_Tunnel(tile, GB(m_railroad[index], 6, 2));
00600             } else {
00601               CP_PlaceRail_Tunnel(tile, m_convert_rail ? (uint) _cur_railtype : GB(m_railroad[index], 6, 2));
00602             }
00603           }
00604         } else if (HasBit(m_railroad[index], 4)) {
00605           /* Bridges: */
00606           /* If we get here, there is a bridge start here. Now find the bridge end 
00607            * TODO Shorten code by setting up variables inside switch statement, and use them inside one loop at the end
00608            */
00609           bool bridge_error = false;
00610           TileIndex tmp_tile = tile;
00611           uint rdd = ReverseDiagDir((DiagDirection)GB(m_railroad[index], 0, 2));
00612           bool found = false;
00613           TileIndex i;
00614           switch (GB(m_railroad[index], 0, 2)) {
00615             case DIAGDIR_NE:
00616               /* -X */
00617               i = 1;
00618               while ((TileX(tile) - i) >= sx) {
00619                 if (GetCPTileType(index - i) == CP_TILE_TUNNELBRIDGE && 
00620                   !HasBit(GetCPMinorTileType(index - i), 0) &&
00621                   !HasBit(m_railroad[index - i], 4) &&
00622                   GB(m_railroad[index - i], 0, 2) == rdd) {
00623                   found = true;
00624                   break;
00625                 }
00626                 i++;
00627               }
00628               if ((TileX(tile) - i) < sx || !found)
00629                 bridge_error = true;
00630               else
00631                 tmp_tile += TileDiffXY(0 - i, 0);
00632               break;
00633             case DIAGDIR_SW:
00634               /* +X */
00635               i = 1;
00636               while ((TileX(tile) + i) < (sx + size_x - 1)) {
00637                 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) {
00638                   found = true;
00639                   break;
00640                 }
00641                 i++;
00642               }
00643               if ((TileX(tile) + i) >= (sx + size_x - 1) || !found)
00644                 bridge_error = true;
00645               else
00646                 tmp_tile += TileDiffXY(+i, 0);
00647               break;
00648             case DIAGDIR_SE:
00649               /* +Y */
00650               i = 1;
00651               while ((TileY(tile) + i) < (sy + size_y - 1)) {
00652                 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) {
00653                   found = true;
00654                   break;
00655                 }
00656                 i++;
00657               }
00658               if ((TileY(tile) + i) >= (sy + size_y - 1) || !found)
00659                 bridge_error = true;
00660               else
00661                 tmp_tile += TileDiffXY(0, +i);
00662               break;
00663             case DIAGDIR_NW:
00664               /* -Y */
00665               i = 1;
00666               while ((TileY(tile) + i) >= (sy + size_y - 1)) {
00667                 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) {
00668                   found = true;
00669                   break;
00670                 }
00671                 i++;
00672               }
00673               if ((TileY(tile) - i) < sy || !found)
00674                 bridge_error = true;
00675               else
00676                 tmp_tile += TileDiffXY(0, 0 - i);
00677               break;
00678           }
00679           if (!bridge_error) {
00680             if (GB(m_railroad[index], 2, 2) == TRANSPORT_RAIL) {
00681               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) );
00682             } else {
00683               CP_Build_Bridge(tile, tmp_tile, m_convert_rail ? GetFastestAvailableBridgeType(GetTunnelBridgeLength(tile, tmp_tile)) : m_signals[index], TRANSPORT_ROAD, ((m_railroad[index] >> 6) & 3U) );
00684             }
00685           }
00686         }
00687         break;
00688       default: break;
00689     }
00690 
00691     index++;
00692 
00693   }
00694 
00695   /* Restore Signals and Waypoints (separated because they depend on underlying track) */
00696   index = 0;
00697   TILE_LOOP(tile, size_x - 1, size_y - 1, TileXY(sx, sy)) {
00698     if (GetCPTileType(index) == CP_TILE_RAIL) {
00699       switch(GetCPMinorTileType(index)) {
00700 /*        case RAIL_TILE_WAYPOINT:
00701           CP_PlaceWaypoint(tile, GB(m_signals[index], 0, 8));
00702           break;*/
00703         case RAIL_TILE_SIGNALS:
00704           PasteSignals(index, tile);
00705       }
00706     }
00707     index++;
00708   }
00709 
00710 
00711   /* If shift is pressed, show the cost estimate. Else play a sound on success */
00712   if (_shift_pressed) {
00713     ShowEstimatedCostOrIncome(m_costs.GetCost(), 100, 100);
00714   }
00715   else {
00716     if (success) SndPlayTileFx(SND_1F_SPLAT, tile);
00717   }
00718 }
00719 
00724 void CopyPaste::PasteArea(TileIndex tile)
00725 {
00726   if (_settings_client.gui.cp_paste_speed != 0xFF) {
00727     this->internal_PasteArea(tile);
00728   }
00729   else {
00730     ShowErrorMessage(STR_COPY_PASTE_PASTE_DISABLED, INVALID_STRING_ID, WL_ERROR, TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
00731   }
00732 }
00733 
00740 void CopyPaste::TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex)
00741 {
00742   /* always restore terrain on this tiles */
00743   SetBit(m_terrain_needed[tindex], 0);
00744   SetBit(m_terrain_needed[tindex + 1], 0);
00745   SetBit(m_terrain_needed[tindex + GetWidth()], 0);
00746   SetBit(m_terrain_needed[tindex + GetWidth() + 1], 0);
00747 }
00748 
00752 void CopyPaste::CopyArea(TileIndex end, TileIndex start)
00753 {
00754   int8 baseh;
00755   TileIndex tindex = 0;
00756   TileIndex bindex = 0;
00757   int size_x, size_y;
00758   bool success = false;
00759   TileIndex sx = TileX(start);
00760   TileIndex sy = TileY(start);
00761   TileIndex ex = TileX(end);
00762   TileIndex ey = TileY(end);
00763   bool tunnelbridge_error;
00764   int32 maxdiff, i;
00765 
00766 
00767   if (ex < sx) Swap(ex, sx);
00768   if (ey < sy) Swap(ey, sy);
00769   /* add one tile, but just for heightmap */
00770   ex++;
00771   ey++;
00772   size_x = (ex - sx) + 1;
00773   size_y = (ey - sy) + 1;
00774 
00775   this->AllocateMapArray(size_x * size_y);
00776   SetWidth(size_x);
00777   SetHeight(size_y);
00778 
00779   /* Create a command DIFF to a flat Area */
00780   /* Base level is from first tile. */
00781   baseh = (int8)TileHeight(TileXY(sx, sy));
00782   tindex = 0;
00783   TILE_LOOP(tile, size_x, size_y, TileXY(sx, sy)) {
00784 
00785     m_heightmap[tindex] = ((int8)TileHeight(tile)) - baseh;
00786     tindex++;
00787 
00788     /* Dont Copy tracks/buildings on last x/y row */
00789     if (cur_h == 1 || cur_w == 1) {
00790       success = true;
00791       continue;
00792     }
00793 
00794     /* Copy building/track here */
00795     switch (GetTileType(tile)) {
00796       case MP_RAILWAY:
00797         /* Check if we want to copy this type of building */
00798         if (!m_copy_with_rail) break;
00799         if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
00800         SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
00801         SB(m_tiletype[bindex], 4, 4, GetRailTileType(tile));
00802         TerrainNeededAroundTile(tindex - 1, bindex);
00803         
00804         /* Store Railway type in bits 6+7 */
00805         SB(m_railroad[bindex], 6, 2, GetRailType(tile));
00806         
00807         switch (GetRailTileType(tile)) {
00808           case RAIL_TILE_DEPOT:
00809             /* Depot here */
00810             /* store direction: bit 2+3 */
00811             SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_RAIL));
00812             break;
00813 /*          case RAIL_TILE_WAYPOINT:
00814             // Waypoint here
00815             // Store Waypoint custom gfx id
00816             SB(m_signals[bindex], 0, 8, GetWaypointByTile(tile)->stat_id);
00817             // Store axis
00818             SB(m_railroad[bindex], 0, 2, AxisToTrackBits(GetWaypointAxis(tile)));
00819             break;*/
00820           case RAIL_TILE_SIGNALS: {
00821             /* Signals: */
00822             /* Store Signal:
00823              * Bit      0 : signal 1 present
00824              * Bit      1 : signal 2 present
00825              * Bit      2 : variant S1
00826              * Bit      3 : variant S2
00827              * Bits: 6- 7 : Direction S1 (Clicks to build)
00828              * Bits: 8- 9 : Direction S2 (Clicks to build)
00829              * Bits: 10-12: signal type S1
00830              * Bits: 13-15: signal type S2
00831              */
00832             bool first_run = true;
00833             for (Track t = TRACK_BEGIN; t < TRACK_END; t++) {
00834               if (HasTrack(tile, t) && HasSignalOnTrack(tile, t)) {
00835                 if (t == TRACK_X || t == TRACK_Y || t == TRACK_LEFT || t == TRACK_UPPER) {
00836                   SetBit(m_signals[bindex], 0);
00837                 } else {
00838                   SetBit(m_signals[bindex], 1);
00839                 }
00840                 /* Store signal direction */
00841                 Trackdir td = TrackToTrackdir(t);
00842                 if (!(HasSignalOnTrackdir(tile, td) && HasSignalOnTrackdir(tile, ReverseTrackdir(td)))) {
00843                   /* one way signal, not 2-way */
00844                   if (t == TRACK_LEFT || t == TRACK_RIGHT) td = ReverseTrackdir(td);
00845                   SB(m_signals[bindex], first_run ? 6 : 8, 2, HasSignalOnTrackdir(tile, td) ? 1 : 2);
00846                 }
00847                 /* Bit 2/3: signal variant(semaphore/electric) ToDo: find some place this can live with another one */
00848                 SB(m_signals[bindex], first_run ? 2 : 3, 1, GetSignalVariant(tile, t));
00849                 /* Bits 10 - 12/13-15: signal type */
00850                 SB(m_signals[bindex], first_run ? 10 : 13, 3, GetSignalType(tile, t));
00851                 first_run = false;
00852               }
00853             }
00854           }
00855           /* fallthrough */
00856           case RAIL_TILE_NORMAL:
00857             /* Store Railway tracks in bits 0 to 5: */
00858             m_railroad[bindex] |= GetTrackBits(tile);
00859             break;
00860         }
00861 
00862         break;
00863       case MP_ROAD:
00864         if (GetRoadTileType(tile) != ROAD_TILE_CROSSING && (!m_copy_with_road || !(m_copy_with_other || IsTileOwner(tile, _current_company)))) break;
00865         SB(m_tiletype[bindex], 0, 4, CP_TILE_ROAD);
00866         SB(m_tiletype[bindex], 4, 4, GetRoadTileType(tile));
00867         switch (GetRoadTileType(tile)) {
00868           case ROAD_TILE_CROSSING: {
00869             /* Crossing: Get Axis, store railtype too 
00870              * TODO Unify...
00871              */
00872             RoadBits roadbits = GetCrossingRoadBits(tile);
00873             Track railtrack = GetCrossingRailTrack(tile);
00874             bool should_copy_rail = m_copy_with_rail && (m_copy_with_other || IsTileOwner(tile, _current_company));
00875             bool should_copy_road = m_copy_with_road;
00876             if (should_copy_rail && !should_copy_road) {
00877               SB(m_tiletype[bindex], 0, 4, CP_TILE_RAIL);
00878               SB(m_tiletype[bindex], 4, 4, RAIL_TILE_NORMAL);
00879               TerrainNeededAroundTile(tindex - 1, bindex);
00880               /* Copy the rail */
00881               m_railroad[bindex] |= TrackToTrackBits(railtrack);
00882               SB(m_railroad[bindex], 6, 2, GetRailType(tile));
00883             }
00884             if (should_copy_road && !should_copy_rail) {
00885               SB(m_tiletype[bindex], 4, 4, ROAD_TILE_NORMAL);
00886             }
00887             if (should_copy_road && should_copy_rail) {
00888               SB(m_signals[bindex], 4, 2, GetRailType(tile));
00889             }
00890             if (should_copy_road) {
00891               /* Copy the road */
00892               for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
00893                 if ((m_copy_with_other || GetRoadOwner(tile, rt) == _current_company) && GetRoadTypes(tile) & RoadTypeToRoadTypes(rt)) {
00894                   TerrainNeededAroundTile(tindex - 1, bindex);
00895                   SB(m_railroad[bindex], rt * 4, 4, roadbits);
00896                 }
00897               }
00898             }
00899             if (!should_copy_road && !should_copy_rail) {
00900               SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
00901             }
00902             } break;
00903 
00904           case ROAD_TILE_DEPOT:
00905             /* Direction: bit 0+1 */
00906             SB(m_railroad[bindex], 0, 2, GetDepotDirection(tile, TRANSPORT_ROAD));
00907             /* Tram or Road? bit 2 */
00908             if (GetRoadTypes(tile) != ROADTYPES_ROAD) SetBit(m_railroad[bindex], 2);
00909             TerrainNeededAroundTile(tindex - 1, bindex);
00910             break;
00911 
00912           case ROAD_TILE_NORMAL:
00913             for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
00914               SB(m_railroad[bindex], rt * 4, 4, GetRoadBits(tile, rt));
00915             }
00916             TerrainNeededAroundTile(tindex - 1, bindex);
00917             SB(m_signals[bindex], 0, 2, GetDisallowedRoadDirections(tile));
00918             break;
00919         }
00920         break;
00921 
00922       case MP_STATION:
00923         /* Stations: currently partially supported */
00924         SB(m_tiletype[bindex], 0, 4, CP_TILE_STATION);
00925 
00926       
00927         switch (GetStationType(tile)) {
00928           /* Road stations */
00929           case STATION_TRUCK:
00930           case STATION_BUS:
00931             SB(m_tiletype[bindex], 4, 4, CP_TILE_ROAD);
00932 
00933             SB(m_railroad[bindex], 0, 2, GetRoadStopDir(tile));
00934             if(GetStationType(tile) == STATION_TRUCK) SetBit(m_railroad[bindex], 2);
00935             SB(m_railroad[bindex], 3, 1, IsDriveThroughStopTile(tile));
00936             SB(m_railroad[bindex], 6, 2, GetRoadTypes(tile));
00937             break;          
00938   
00939           /* Rail stations */
00940           case STATION_RAIL:
00941             SB(m_tiletype[bindex], 4, 4, CP_TILE_RAIL);
00942 
00943             //GetStationSpec for newgrf info
00944             break;
00945 
00946           default:
00947             /* Not reached */
00948             break;
00949 
00950         }
00951         break;
00952 
00953       case MP_TUNNELBRIDGE:
00954         /* Check for tunnel or bridge 
00955          * TODO Try to unify bridges an tunnels, since error checking(start/endtile) is essentially the same
00956          */
00957         if (IsTunnelTile(tile)) {
00958           /* Storing Tunnel */
00959           if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
00960           if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
00961           if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
00962           tunnelbridge_error = false;
00963           if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
00964             int tilediff = 1;
00965             /* Store tunnel direction in bit 0-1 */
00966             SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
00967             /* Store tunnel transport type in bit 2-3 */
00968             SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
00969             /* Store tunnel start in bit 4 */
00970             SetBit(m_railroad[bindex], 4);
00971             /* Store rail type too, if it is a railtunnel */
00972             if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
00973               m_railroad[bindex] |= (GetRailType(tile) << 6);
00974             if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
00975               m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
00976             /* Now mark all tiles between tunnel start and end as needed 
00977              * TODO Unify... ;)
00978              */
00979             switch (GetTunnelBridgeDirection(tile)) {
00980               case DIAGDIR_SW:
00981                 maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
00982                 if (maxdiff <= 0) {
00983                   tunnelbridge_error = true;
00984                   break;
00985                 }
00986                 while ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
00987                   tilediff++;
00988                 }
00989                 if ((!IsTunnelTile(tile + TileDiffXY(tilediff, 0))) || (tilediff > maxdiff))
00990                   tunnelbridge_error = true;
00991                 if (!tunnelbridge_error) {
00992                   /* Mark Tiles as needed: */
00993                   for (i = 0; i <= tilediff; i++)
00994                     TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
00995 
00996                   /* Set other TunnelEnd */
00997                   SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
00998                   SB(m_tiletype[bindex + tilediff], 4, 1, true);
00999                   /* Store tunnel direction in bit 1-2 */
01000                   m_railroad[bindex + tilediff] |= GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0));
01001                   /* Store tunnel transport type in bit 3 */
01002                   SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
01003                   /* Store tunnel start in bit 4 (No, this is tunnel End) */
01004                   /* Store rail type too, if railtunnel */
01005                   if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
01006                     m_railroad[bindex + tilediff] = (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
01007                 }
01008                 break;
01009               case DIAGDIR_SE:
01010                 maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
01011                 if (maxdiff <= 0) {
01012                   tunnelbridge_error = true;
01013                   break;
01014                 }
01015                 while ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) && (tilediff <= maxdiff)) { //InsideSelection, tunnelEndnotfound
01016                   tilediff++;
01017                 }
01018                 if ((!IsTunnelTile(tile + TileDiffXY(0, tilediff))) || (tilediff > maxdiff))
01019                   tunnelbridge_error = true;
01020                 if (!tunnelbridge_error) {
01021                   /* Mark Tiles as needed: */
01022                   for (i = 0; i <= tilediff; i++)
01023                     TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
01024 
01025                   /* Set other TunnelEnd */
01026                   SB(m_tiletype[bindex + tilediff * (size_x - 1)], 0, 4, CP_TILE_TUNNELBRIDGE);
01027                   SB(m_tiletype[bindex + tilediff * (size_x - 1)], 4, 1, true);
01028                   /* Store tunnel direction in bit 0-1 */
01029                   m_railroad[bindex + (tilediff * (size_x - 1))] |= GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff));
01030                   /* Store tunnel transport type in bit 3 */
01031                   SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
01032                   /* Store tunnel start in bit 4 (No, this is tunnel End) */
01033                   /* Store rail type too, if railtunnel */
01034                   if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
01035                     m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
01036                 }
01037                 break;
01038               default:
01039               break;
01040             }
01041             if (tunnelbridge_error) {
01042               /* ResetBridge on Error */
01043               m_railroad[bindex] = 0;
01044             } else {
01045               SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
01046               SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
01047             }
01048           }
01049           else {
01050             /* Other directions: do nothing since we have everything copied already */
01051           }
01052         }
01053         else {
01054           /* Store bridge (Has to be in "else", since Tunnel is a "BridgeRamp" too) */
01055           if (IsBridge(tile)) {
01056             if (!m_copy_with_rail && (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)) break;
01057             if (!m_copy_with_road && (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)) break;
01058             if (!(m_copy_with_other || IsTileOwner(tile, _current_company))) break;
01059 
01060             tunnelbridge_error = false;
01061             if ((GetTunnelBridgeDirection(tile) == DIAGDIR_SW) || (GetTunnelBridgeDirection(tile) == DIAGDIR_SE)) {
01062               int tilediff = 1;
01063               /* Direction bit 0-1 */
01064               SB(m_railroad[bindex], 0, 2, GetTunnelBridgeDirection(tile));
01065               /* TransportType bit 3 */
01066               SB(m_railroad[bindex], 2, 2, GetTunnelBridgeTransportType(tile));
01067               /* Store "IsBridge-Start" in Bit4 */
01068               SetBit(m_railroad[bindex], 4);
01069               /* BridgeType in m_signals */
01070               m_signals[bindex] = GetBridgeType(tile);
01071               /* Store Railtype */
01072               if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL)
01073                 m_railroad[bindex] |= (GetRailType(tile) << 6);
01074               if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD)
01075                 m_railroad[bindex] |= (GetRoadTypes(tile) << 6);
01076               /* Now mark all tiles between bridge start and end as needed 
01077                * TODO: Unify :)
01078                */
01079               switch (GetTunnelBridgeDirection(tile)) {
01080                 TileIndex otherEnd;
01081                 case DIAGDIR_SW:
01082                   maxdiff = (size_x - 1) - (bindex % (size_x - 1)) - 1;
01083                   if (maxdiff <= 0) {
01084                     tunnelbridge_error = true;
01085                     break;
01086                   }
01087                   otherEnd = GetOtherBridgeEnd(tile);
01088                   tilediff = DistanceManhattan(tile, otherEnd);
01089                   if (tilediff > maxdiff)
01090                     tunnelbridge_error = true;
01091                   
01092                   if (!tunnelbridge_error) {
01093                     /* Mark Tiles as needed: */
01094                     for (i = 0; i <= tilediff; i++)
01095                       TerrainNeededAroundTile(tindex - 1 + i, bindex + i);
01096 
01097                     /* Set other BridgeEnd */
01098                     SB(m_tiletype[bindex + tilediff], 0, 4, CP_TILE_TUNNELBRIDGE);
01099                     SB(m_tiletype[bindex + tilediff], 4, 1, IsTunnelTile(tile));
01100                     /* Direction bit 0-1 */
01101                     SB(m_railroad[bindex + tilediff], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(tilediff, 0)));
01102                     /* TransportType bit 3 */
01103                     SB(m_railroad[bindex + tilediff], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)));
01104                     /* Store "IsBridge-Start" in Bit4 (Nope, this is the Bridge-End) */
01105                     
01106                     /* BridgeType in m_signals */
01107                     m_signals[bindex + tilediff] = GetBridgeType(tile + TileDiffXY(tilediff, 0));
01108                     /* Store Railtype */
01109                     if (GetTunnelBridgeTransportType(tile + TileDiffXY(tilediff, 0)) == TRANSPORT_RAIL)
01110                       m_railroad[bindex + tilediff] |= (GetRailType(tile + TileDiffXY(tilediff, 0)) << 6);
01111                   }
01112                   break;
01113                 case DIAGDIR_SE:
01114                   maxdiff = (size_y - 1) - (bindex / (size_x - 1)) - 1;
01115                   if (maxdiff <= 0) {
01116                     tunnelbridge_error = true;
01117                     break;
01118                   }
01119                   otherEnd = GetOtherBridgeEnd(tile);
01120                   tilediff = DistanceManhattan(tile, otherEnd);
01121                   if (tilediff > maxdiff)
01122                     tunnelbridge_error = true;
01123                   if (!tunnelbridge_error) {
01124                     /* Mark Tiles as needed: */
01125                     for (i = 0; i <= tilediff; i++)
01126                       TerrainNeededAroundTile(tindex - 1 + (i * size_x), bindex + (i * (size_x - 1)));
01127 
01128                     /* Set other BridgeEnd */
01129                     SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 0, 4, CP_TILE_TUNNELBRIDGE);
01130                     SB(m_tiletype[bindex + (tilediff * (size_x - 1))], 4, 1, IsTunnelTile(tile));
01131                     /* Direction bit 0-1 */
01132                     SB(m_railroad[bindex + tilediff * (size_x - 1)], 0, 2, GetTunnelBridgeDirection(tile + TileDiffXY(0, tilediff)));
01133                     /* TransportType bit 3 */
01134                     SB(m_railroad[bindex + tilediff * (size_x - 1)], 2, 2, GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)));
01135                     /* Store "IsBridge-Start" in Bit4 (Nope, this is the End) */
01136                     /* BridgeType  in m_signals */
01137                     m_signals[bindex + tilediff * (size_x - 1)] = GetBridgeType(tile + TileDiffXY(0, tilediff));
01138                     /* Store Railtype */
01139                     if (GetTunnelBridgeTransportType(tile + TileDiffXY(0, tilediff)) == TRANSPORT_RAIL)
01140                       m_railroad[bindex + (tilediff * (size_x - 1))] |= (GetRailType(tile + TileDiffXY(0, tilediff)) << 6);
01141                   }
01142                   break;
01143                 default:
01144                   break;
01145               }
01146               if (tunnelbridge_error) {
01147                 /* ResetBridge on Error */
01148                 m_railroad[bindex] = 0;
01149                 m_signals[bindex] = 0;
01150               } else {
01151                 SB(m_tiletype[bindex], 0, 4, CP_TILE_TUNNELBRIDGE);
01152                 SB(m_tiletype[bindex], 4, 1, IsTunnelTile(tile));
01153               }
01154             }
01155             else {
01156               /* Other directions, do nothing, since we have copied everything already */
01157             }
01158           }
01159         }
01160         break;
01161 
01162       default:
01163         SB(m_tiletype[bindex], 0, 4, CP_TILE_CLEAR);
01164         /* Storing nothing */
01165         break;
01166     }
01167     bindex++;
01168     success = true;
01169 
01170   }
01171 
01172   if (success) SndPlayTileFx(SND_1F_SPLAT, end);
01173 }
01174 
01175 /* Get the height of a tile */
01176 uint CopyPaste::GetHeight(uint baseh, uint index)
01177 {
01178   return baseh + m_heightmap[index];
01179 }
01180 
01181 Slope CopyPaste::GetSlope(uint index)
01182 {
01183   int a = m_heightmap[index];
01184   int min = a;
01185   int b = m_heightmap[index + 1];
01186   if (min > b) min = b;
01187   int c = m_heightmap[index + GetWidth()];
01188   if (min > c) min = c;
01189   int d = m_heightmap[index + GetWidth() + 1];
01190   if (min > d) min = d;
01191   
01192   uint r = SLOPE_FLAT;
01193   
01194   if (a -= min != 0) r += (--a << 4) + SLOPE_N;
01195   if (c -= min != 0) r += (--c << 4) + SLOPE_E;
01196   if (d -= min != 0) r += (--d << 4) + SLOPE_S;
01197   if (b -= min != 0) r += (--b << 4) + SLOPE_W;
01198   
01199   return (Slope)r;
01200 }
01201 
01202 TrackBits CopyPaste::GetCPTrackBits(uint index)
01203 {
01204   if (GetCPTileType(index) == CP_TILE_RAIL) {
01205     if (GetCPMinorTileType(index) != RAIL_TILE_DEPOT) return (TrackBits)GB(m_railroad[index], 0, 6);
01206   } else if (GetCPTileType(index) == CP_TILE_ROAD) {
01207     if (GetCPMinorTileType(index) == ROAD_TILE_CROSSING) return GB(m_railroad[index], 0, 4) == ROAD_X ? TRACK_BIT_Y : TRACK_BIT_X;
01208   }
01209   return TRACK_BIT_NONE;
01210 }
01211 
01213 CopyPaste::CopyPasteTileType CopyPaste::GetCPTileType(uint index)
01214 {
01215   return (CopyPasteTileType)GB(m_tiletype[index], 0, 4);
01216 }
01217 
01219 uint CopyPaste::GetCPMinorTileType(uint index)
01220 {
01221   return GB(m_tiletype[index], 4, 4);
01222 }
01228 template <typename T> 
01229 static void rotate(T* b, int w, int h, int dir)
01230 {
01231   int i, len, x, y, src, target;
01232 
01233   /* Allocate a temporary array */
01234   len = w * h;
01235   T* tmp = MallocT<T>(len);
01236 
01237   /* Copy array to new allocated array: */
01238   for (i = 0; i < len; i++)
01239     tmp[i] = b[i];
01240 
01241   /* Copy rotated values back to original array */
01242   if (dir == 1) {
01243     for (y = 0; y < h; y++) {
01244       for (x = 0; x < w; x++) {
01245         /*X index is now the old Y index
01246          * Y index is w - x
01247          */
01248         src = (y * w) + x;
01249         target = (((w - 1) - x) * h) + y;
01250         b[target] = tmp[src];
01251       }
01252     }
01253   }
01254   else if (dir == -1) {
01255       /* Copy rotated values back to original array */
01256       for (y = 0; y < h; y++) {
01257         for (x = 0; x < w; x++) {
01258           /* X index is now the old Y index
01259            * Y index is w - x
01260            */
01261           src = (y * w) + x;
01262           target = (x * h) + (h - 1 - y);
01263           b[target] = tmp[src];
01264         }
01265       }
01266   }
01267 
01268   /* Release temp array */
01269   free(tmp);
01270 }
01271 
01277 template <typename T>
01278 static void mirror(T* b, int w, int h, Axis axis)
01279 {
01280   int x, y;
01281 
01282 
01283   switch (axis) {
01284     case AXIS_X:
01285       for (y = 0; y < h; y++) {
01286         for (x = 0; x < (w / 2); x++) {
01287           Swap<T>(b[x + (y * w)], b[(w - x - 1) + (y * w)]);
01288         }
01289       }
01290     break;
01291     case AXIS_Y:
01292       for (y = 0; y < (h / 2); y++) {
01293         for (x = 0; x < w; x++) {
01294           Swap<T>(b[x + (y * w)], b[ x + ((h - y - 1) * w)]);
01295         }
01296       }
01297     break;
01298     default: NOT_REACHED();
01299   }
01300 }
01301 
01307 void CopyPaste::RotateSelectionCW()
01308 {
01309   int w = GetWidth() - 1;
01310   int h = GetHeight() - 1;
01311   uint8 storelocation;
01312   int index, len;
01313 
01314   uint8 tmp8;
01315   uint16 tmp16;
01316 
01317   /* Rotate array indices */
01318   rotate(m_heightmap, GetWidth(), GetHeight(), 1);
01319   rotate(m_terrain_needed, GetWidth(), GetHeight(), 1);
01320   rotate(m_tiletype, w, h, 1);
01321   rotate(m_railroad,   w, h, 1);
01322   rotate(m_signals,w, h, 1);
01323 
01324   /* Rotate array content (tracks, depots etc..) */
01325   len = w * h;
01326   for (index = 0; index < len; index++) {
01327 
01328     switch (GetCPTileType(index)) {
01329       case CP_TILE_RAIL:
01330         if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01331           /* Depot */
01332           SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01333           break;
01334         }
01335         /* Rotate Tracks */
01336         /* Copy tracks to temp variable */
01337         tmp8 = m_railroad[index];
01338         /* Clear Tracks: bits 0-5 */
01339         m_railroad[index] &= ~((1 << 6) - 1);
01340         /* Copy back + rotate 
01341          * TODO exchange with arithmetic or lookup-table version...shorten...
01342          */
01343         if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_X;
01344         if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_Y;
01345         if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
01346         if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
01347         if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
01348         if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
01349         
01350         if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01351           /* Signals */
01352           /* copy original signals to temporary variable */
01353           tmp16 = m_signals[index];
01354           /* Clear Signals: Bits 0-2 */
01355           ClrBit(m_signals[index], 0);
01356           ClrBit(m_signals[index], 1);
01357           /* Copy back + rotate position */
01358           storelocation = 6;
01359           /* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
01360           if ((m_railroad[index] & TRACK_BIT_Y) && HasBit(tmp16, 0)) {
01361             SetBit(m_signals[index], 0);
01362           }
01363           if ((m_railroad[index] & TRACK_BIT_X) && HasBit(tmp16, 0)) {
01364             SetBit(m_signals[index], 0);
01365             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01366           }
01367           if ((m_railroad[index] & TRACK_BIT_RIGHT) && HasBit(tmp16, 0)) {
01368             SetBit(m_signals[index], 1);
01369             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01370             storelocation = 8;
01371           }
01372           if ((m_railroad[index] & TRACK_BIT_LEFT) && HasBit(tmp16, 1)) {
01373             SetBit(m_signals[index], 0);
01374             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01375             if (storelocation == 8) {
01376               /* Exchange Storelocations */
01377               SwapSignalInfo(index);
01378             }
01379             storelocation = 8;
01380           }
01381           if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
01382             SetBit(m_signals[index], 0);
01383           }
01384           if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
01385             SetBit(m_signals[index], 1);
01386           }
01387         
01388         }
01389         break;
01390         
01391       case CP_TILE_ROAD:
01392         if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01393           /* Depot */
01394           SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01395           break;
01396         }
01397 
01398         /* rotate one-way roads */
01399         if (m_railroad[index] & ROAD_Y && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01400           SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01401         }
01402         /* Road: */
01403         SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90RIGHT));
01404         /* Trams: */
01405         SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90RIGHT));
01406 
01407       
01408         break;
01409 
01410         case CP_TILE_TUNNELBRIDGE:
01411           /* tunnel/bridge */
01412           SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90RIGHT));
01413         
01414           break;
01415 
01416         default: break;
01417     }
01418 
01419   }
01420 
01421   Swap(this->m_width, this->m_height);
01422 }
01423 
01429 void CopyPaste::RotateSelectionCCW()
01430 {
01431   int w = GetWidth() - 1;
01432   int h = GetHeight() - 1;
01433   uint8 storelocation;
01434   int index, len;
01435 
01436   uint8 tmp8;
01437   uint16 tmp16;
01438 
01439   /* Rotate array indices */
01440   rotate(m_heightmap, GetWidth(), GetHeight(), -1);
01441   rotate(m_terrain_needed, GetWidth(), GetHeight(), -1);
01442   rotate(m_tiletype, w, h, -1);
01443   rotate(m_railroad,   w, h, -1);
01444   rotate(m_signals,w, h, -1);
01445 
01446   /* Rotate array content (tracks, depots etc..) */
01447   len = w * h;
01448   for (index = 0; index < len; index++) {
01449     switch (GetCPTileType(index)) {
01450       case CP_TILE_RAIL:
01451         if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01452           //Depot
01453           SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01454           break;
01455         }
01456         tmp8 = m_railroad[index];
01457         /* Clear Tracks: bits 0-5 */
01458         m_railroad[index] &= ~63U;
01459         /* Copy back + rotate */
01460         if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_X;
01461         if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_Y;
01462         if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
01463         if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
01464         if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
01465         if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
01466         if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01467           //Signals
01468           //Rotate position
01469           tmp16 = m_signals[index];
01470           /* Clear Signals: Bits 0-2 */
01471           ClrBit(m_signals[index], 0);
01472           ClrBit(m_signals[index], 1);
01473           //Copy back + rotate position
01474           storelocation = 6;
01475           /* We already rotated the rail, so the TRACK_BIT_xxxx are the rotated ones */
01476           if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
01477             SetBit(m_signals[index], 0);
01478             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01479           }
01480           if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01481             SetBit(m_signals[index], 0);
01482           }
01483           if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
01484             SetBit(m_signals[index], 0);
01485             storelocation = 8;
01486           }
01487           if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
01488             SetBit(m_signals[index], 1);
01489             storelocation = 8;
01490           }
01491           if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
01492             SetBit(m_signals[index], 1);
01493             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01494             storelocation = 8;
01495           }
01496           if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
01497             SetBit(m_signals[index], 0);
01498             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01499             if (storelocation == 8) {
01500               /* Exchange Storelocations */
01501               SwapSignalInfo(index);
01502             }
01503             storelocation = 8;
01504           }
01505         }
01506         break;
01507 
01508       case CP_TILE_ROAD:
01509         if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01510           //Depot
01511           SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01512           break;
01513         }
01514         if (m_railroad[index] & ROAD_X && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01515           SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01516         }
01517         //Road & Tram:
01518         SB(m_railroad[index], 0, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 0, 4), DIAGDIRDIFF_90LEFT));
01519         SB(m_railroad[index], 4, 4, RotateRoadBits((RoadBits)GB(m_railroad[index], 4, 4), DIAGDIRDIFF_90LEFT));
01520 
01521         break;
01522 
01523       case CP_TILE_TUNNELBRIDGE:
01524         SB(m_railroad[index], 0, 2, ChangeDiagDir((DiagDirection)GB(m_railroad[index], 0, 2), DIAGDIRDIFF_90LEFT));
01525         break;
01526       default: break;
01527     }
01528 
01529   }
01530 
01531   Swap(this->m_height, this->m_width);
01532 }
01533 
01534 void CopyPaste::MirrorSelectionHorizontal()
01535 {
01536   int w = GetWidth() - 1;
01537   int h = GetHeight() - 1;
01538   uint8 storelocation;
01539   int index, len;
01540 
01541   uint8 tmp8;
01542   uint16 tmp16;
01543 
01544   /* Mirror array indices */
01545   mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_X);
01546   mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_X);
01547   mirror(m_tiletype, w, h, AXIS_X);
01548   mirror(m_railroad,   w, h, AXIS_X);
01549   mirror(m_signals,w, h, AXIS_X);
01550 
01551   /* Mirror array content (left <-> right) */
01552   len = w * h;
01553   for (index = 0; index < len; index++) {
01554     switch (GetCPTileType(index)) {
01555       case CP_TILE_RAIL:
01556         if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01557           //Depot
01558           tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
01559           if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01560           SB(m_railroad[index], 0, 2, tmp8); // set
01561           break;
01562         }
01563         tmp8 = m_railroad[index];
01564         /* Clear Tracks: Bits 0-5 */
01565         m_railroad[index] &= ~63U;
01566         /* Copy back + mirror */
01567         if (tmp8 & TRACK_BIT_X)     m_railroad[index] |= TRACK_BIT_X;
01568         if (tmp8 & TRACK_BIT_Y)     m_railroad[index] |= TRACK_BIT_Y;
01569         if (tmp8 & TRACK_BIT_LEFT)  m_railroad[index] |= TRACK_BIT_UPPER;
01570         if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_LOWER;
01571         if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_LEFT;
01572         if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_RIGHT;
01573         
01574         if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01575           //Signals
01576           //Mirror position
01577           tmp16 = m_signals[index];
01578           //Copy back + mirror position
01579           storelocation = 6;
01580           if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01581             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01582           }
01583           if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 0)) {
01584             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01585             storelocation = 8;
01586           }
01587           if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 1)) {
01588             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01589             storelocation = 8;
01590           }
01591           if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 0)) {
01592             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01593             storelocation = 8;
01594           }
01595           if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 1)) {
01596             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01597             storelocation = 8;
01598           }
01599         }
01600         break;
01601 
01602       case CP_TILE_ROAD:
01603         if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01604           //Depot
01605           tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
01606           if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01607           SB(m_railroad[index], 0, 2, tmp8); // set
01608           break;
01609         }
01610         //Road:
01611         //swap horizontal roadpieces
01612         tmp8 = m_railroad[index];
01613         m_railroad[index] &= ~(ROAD_NE | ROAD_SW  | ((ROAD_NE | ROAD_SW) << 4)); //Clear specific road bits
01614         if ((tmp8 & ROAD_NE) > 0) m_railroad[index] |= ROAD_SW;
01615         if ((tmp8 & ROAD_SW) > 0) m_railroad[index] |= ROAD_NE;
01616         if ((tmp8 & (ROAD_NE << 4)) > 0) m_railroad[index] |= (ROAD_SW << 4);
01617         if ((tmp8 & (ROAD_SW << 4)) > 0) m_railroad[index] |= (ROAD_NE << 4);
01618         
01619         if ((tmp8 & ROAD_X) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01620           SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01621         }
01622         
01623         break;
01624 
01625       case CP_TILE_TUNNELBRIDGE:
01626         /* Tunnel/Bridge
01627          * just mirror direction
01628          */
01629         tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 001
01630         if (tmp8 == DIAGDIR_NE || tmp8 == DIAGDIR_SW) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01631         SB(m_railroad[index], 0, 2, tmp8); // set
01632       
01633         break;
01634 
01635       default: break;
01636     }
01637 
01638   }
01639 }
01640 
01641 void CopyPaste::MirrorSelectionVertical()
01642 {
01643   int w = GetWidth() - 1;
01644   int h = GetHeight() - 1;
01645   uint8 storelocation;
01646   int index, len;
01647 
01648   uint8 tmp8;
01649   uint16 tmp16;
01650 
01651   //Mirror arrays
01652   mirror(m_heightmap, GetWidth(), GetHeight(), AXIS_Y);
01653   mirror(m_terrain_needed, GetWidth(), GetHeight(), AXIS_Y);
01654   mirror(m_tiletype, w, h, AXIS_Y);
01655   mirror(m_railroad,   w, h, AXIS_Y);
01656   mirror(m_signals,w, h, AXIS_Y);
01657 
01658   //Mirror array content (up <-> down)
01659   len = w * h;
01660   for (index = 0; index < len; index++) {
01661     switch (GetCPTileType(index)) {
01662       case CP_TILE_RAIL:
01663         if (GetCPMinorTileType(index) == RAIL_TILE_DEPOT) {
01664           //Depot
01665           tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
01666           if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01667           SB(m_railroad[index], 0, 2, tmp8); // set
01668           break;
01669         }
01670         tmp8 = m_railroad[index];
01671         //Clear Tracks
01672         m_railroad[index] &= ~63U; //Clear bits 0-5
01673         //Copy back + mirror
01674         if (tmp8 & TRACK_BIT_X) m_railroad[index]     |= TRACK_BIT_X;
01675         if (tmp8 & TRACK_BIT_Y) m_railroad[index]     |= TRACK_BIT_Y;
01676         if (tmp8 & TRACK_BIT_RIGHT) m_railroad[index] |= TRACK_BIT_UPPER;
01677         if (tmp8 & TRACK_BIT_LEFT) m_railroad[index]  |= TRACK_BIT_LOWER;
01678         if (tmp8 & TRACK_BIT_LOWER) m_railroad[index] |= TRACK_BIT_LEFT;
01679         if (tmp8 & TRACK_BIT_UPPER) m_railroad[index] |= TRACK_BIT_RIGHT;
01680         if (GetCPMinorTileType(index) == RAIL_TILE_SIGNALS) {
01681           //Signals
01682           //Mirror position
01683           tmp16 = m_signals[index];
01684           //Clear Signals
01685           ClrBit(m_signals[index], 0);
01686           ClrBit(m_signals[index], 1);
01687           //Copy back + mirror position
01688           storelocation = 6;
01689           if (m_railroad[index] & TRACK_BIT_X && HasBit(tmp16, 0)) {
01690             SetBit(m_signals[index], 0);
01691           }
01692           if (m_railroad[index] & TRACK_BIT_Y && HasBit(tmp16, 0)) {
01693             SetBit(m_signals[index], 0);
01694             SB(m_signals[index], storelocation, 2, MirrorSignalDirection(GB(m_signals[index], storelocation, 2)));
01695           }
01696           if (m_railroad[index] & TRACK_BIT_RIGHT && HasBit(tmp16, 0)) {
01697             SetBit(m_signals[index], 1);
01698             storelocation = 8;
01699           }
01700           if (m_railroad[index] & TRACK_BIT_LEFT && HasBit(tmp16, 1)) {
01701             SetBit(m_signals[index], 0);
01702             if (storelocation == 8) {
01703               /* Exchange Storelocations */
01704               SwapSignalInfo(index);
01705             }
01706             storelocation = 8;
01707           }
01708           if (m_railroad[index] & TRACK_BIT_LOWER && HasBit(tmp16, 0)) {
01709             SetBit(m_signals[index], 1);
01710             storelocation = 8;
01711           }
01712           if (m_railroad[index] & TRACK_BIT_UPPER && HasBit(tmp16, 1)) {
01713             SetBit(m_signals[index], 0);
01714             if (storelocation == 8) {
01715               /* Exchange Storelocations */
01716               SwapSignalInfo(index);
01717             }
01718             storelocation = 8;
01719           }
01720 
01721         }
01722         break;
01723 
01724       case CP_TILE_ROAD:
01725         if (GetCPMinorTileType(index) == ROAD_TILE_DEPOT) {
01726           //Depot
01727           tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 0-1
01728           if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01729           SB(m_railroad[index], 0, 2, tmp8); // set
01730           break;
01731         }
01732         //Road:
01733         //swap horizontal roadpieces
01734         tmp8 = m_railroad[index];
01735         m_railroad[index] &= ~(ROAD_NW | ROAD_SE  | ((ROAD_NW | ROAD_SE) << 4)); //Clear specific road bits
01736         if ((tmp8 & ROAD_NW) > 0) m_railroad[index] |= ROAD_SE;
01737         if ((tmp8 & ROAD_SE) > 0) m_railroad[index] |= ROAD_NW;
01738         if ((tmp8 & (ROAD_NW << 4)) > 0) m_railroad[index] |= (ROAD_SE << 4);
01739         if ((tmp8 & (ROAD_SE << 4)) > 0) m_railroad[index] |= (ROAD_NW << 4);
01740         
01741         if ((tmp8 & ROAD_Y) && GetCPMinorTileType(index) == ROAD_TILE_NORMAL) {
01742           SB(m_signals[index], 0, 2, MirrorOneWayRoadDirection((DisallowedRoadDirections)GB(m_signals[index], 0, 2)));
01743         }
01744         
01745         break;
01746 
01747       case CP_TILE_TUNNELBRIDGE:
01748         /* Tunnel / Bridge */
01749         tmp8 = GB(m_railroad[index], 0, 2); //Extract bit 1-2
01750         if (tmp8 == DIAGDIR_NW || tmp8 == DIAGDIR_SE) tmp8 = ReverseDiagDir((DiagDirection)tmp8);
01751         SB(m_railroad[index], 0, 2, tmp8); // set
01752         break;
01753       default: break;
01754     }
01755 
01756   }
01757 }
01758 
01759