# 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