(svn r9915) [NoAI] -Sync with trunk -r9815:9914 noai
authorglx
Fri, 25 May 2007 00:25:08 +0000
branchnoai
changeset 9624 b71483f2330f
parent 9623 ee0173281563
child 9625 3301b1b3889c
(svn r9915) [NoAI] -Sync with trunk -r9815:9914
bin/data/group.grf
config.lib
docs/landscape.html
docs/landscape_grid.html
projects/openttd.vcproj
projects/openttd_vs80.vcproj
readme.txt
source.list
src/ai/api/ai_order.cpp
src/ai/api/ai_road.cpp
src/ai/api/ai_vehicle.cpp
src/aircraft_cmd.cpp
src/aircraft_gui.cpp
src/airport_gui.cpp
src/autoreplace_cmd.cpp
src/autoreplace_gui.cpp
src/bridge_map.h
src/build_vehicle_gui.cpp
src/cargotype.cpp
src/clear_cmd.cpp
src/command.cpp
src/command.h
src/depot.cpp
src/depot.h
src/depot_gui.cpp
src/disaster_cmd.cpp
src/dock_gui.cpp
src/dummy_land.cpp
src/economy.cpp
src/economy.h
src/engine.cpp
src/engine.h
src/functions.h
src/gfx.cpp
src/gfx.h
src/gfxinit.cpp
src/group.h
src/group_cmd.cpp
src/group_gui.cpp
src/gui.h
src/industry.h
src/industry_cmd.cpp
src/industry_gui.cpp
src/industry_map.h
src/landscape.cpp
src/landscape.h
src/lang/american.txt
src/lang/brazilian_portuguese.txt
src/lang/bulgarian.txt
src/lang/czech.txt
src/lang/danish.txt
src/lang/dutch.txt
src/lang/english.txt
src/lang/estonian.txt
src/lang/french.txt
src/lang/german.txt
src/lang/hungarian.txt
src/lang/italian.txt
src/lang/japanese.txt
src/lang/korean.txt
src/lang/russian.txt
src/lang/slovak.txt
src/lang/slovenian.txt
src/lang/spanish.txt
src/lang/swedish.txt
src/lang/traditional_chinese.txt
src/lang/turkish.txt
src/lang/ukrainian.txt
src/main_gui.cpp
src/misc.cpp
src/misc_gui.cpp
src/network/network_server.cpp
src/newgrf.cpp
src/newgrf_cargo.cpp
src/newgrf_commons.cpp
src/newgrf_commons.h
src/newgrf_engine.cpp
src/newgrf_engine.h
src/newgrf_house.cpp
src/newgrf_house.h
src/newgrf_spritegroup.cpp
src/newgrf_station.cpp
src/news_gui.cpp
src/npf.cpp
src/npf.h
src/oldloader.cpp
src/openttd.cpp
src/openttd.h
src/order_cmd.cpp
src/pathfind.cpp
src/pathfind.h
src/player.h
src/players.cpp
src/rail_cmd.cpp
src/rail_gui.cpp
src/road.h
src/road_cmd.cpp
src/road_cmd.h
src/road_gui.cpp
src/road_map.cpp
src/road_map.h
src/roadveh_cmd.cpp
src/roadveh_gui.cpp
src/saveload.cpp
src/screenshot.cpp
src/settings.cpp
src/settings_gui.cpp
src/ship_cmd.cpp
src/ship_gui.cpp
src/signs.cpp
src/smallmap_gui.cpp
src/sound.cpp
src/station.cpp
src/station.h
src/station_cmd.cpp
src/station_gui.cpp
src/station_map.h
src/stdafx.h
src/strgen/strgen.cpp
src/strings.cpp
src/table/build_industry.h
src/table/cargo_const.h
src/table/control_codes.h
src/table/engines.h
src/table/files.h
src/table/sprites.h
src/table/town_land.h
src/terraform_gui.cpp
src/texteff.cpp
src/town.h
src/town_cmd.cpp
src/town_gui.cpp
src/train_cmd.cpp
src/train_gui.cpp
src/tree_cmd.cpp
src/tunnel_map.h
src/tunnelbridge_cmd.cpp
src/unix.cpp
src/unmovable_cmd.cpp
src/variables.h
src/vehicle.cpp
src/vehicle.h
src/vehicle_gui.cpp
src/vehicle_gui.h
src/video/dedicated_v.cpp
src/video/null_v.cpp
src/video/sdl_v.cpp
src/video/win32_v.cpp
src/viewport.cpp
src/viewport.h
src/water_cmd.cpp
src/win32.cpp
src/window.cpp
src/window.h
src/yapf/follow_track.hpp
src/yapf/yapf.hpp
src/yapf/yapf_destrail.hpp
src/yapf/yapf_road.cpp
src/yapf/yapf_ship.cpp
src/zoom.hpp
Binary file bin/data/group.grf has changed
--- a/config.lib	Fri May 11 15:13:08 2007 +0000
+++ b/config.lib	Fri May 25 00:25:08 2007 +0000
@@ -313,10 +313,10 @@
 		echo " Available options are: --endian=[AUTO|LE|BE]"
 		exit 1
 	fi
-	# OS only allows DETECT, UNIX, OSX, FREEBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP
-	if [ -z "`echo $os | egrep '^(DETECT|UNIX|OSX|FREEBSD|MORPHOS|BEOS|SUNOS|CYGWIN|MINGW|OS2|WINCE|PSP)$'`" ]; then
+	# OS only allows DETECT, UNIX, OSX, FREEBSD, OPENBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP
+	if [ -z "`echo $os | egrep '^(DETECT|UNIX|OSX|FREEBSD|OPENBSD|MORPHOS|BEOS|SUNOS|CYGWIN|MINGW|OS2|WINCE|PSP)$'`" ]; then
 		echo "configure: error: invalid option --os=$os"
-		echo " Available options are: --os=[DETECT|UNIX|OSX|FREEBSD|MORPHOS|BEOS|SUNOS|CYGWIN|MINGW|OS2|WINCE|PSP]"
+		echo " Available options are: --os=[DETECT|UNIX|OSX|FREEBSD|OPENBSD|MORPHOS|BEOS|SUNOS|CYGWIN|MINGW|OS2|WINCE|PSP]"
 		exit 1
 	fi
 	# cpu_type can be either 32 or 64
@@ -731,7 +731,7 @@
 		CFLAGS="$CFLAGS -fno-strict-aliasing"
 	fi
 
-	if [ "$os" != "CYGWIN" ] && [ "$os" != "FREEBSD" ] && [ "$os" != "MINGW" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ]; then
+	if [ "$os" != "CYGWIN" ] && [ "$os" != "FREEBSD" ] && [ "$os" != "OPENBSD" ] && [ "$os" != "MINGW" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ]; then
 		LIBS="$LIBS -lpthread"
 		LIBS="$LIBS -lrt"
 	fi
@@ -755,6 +755,10 @@
 		CFLAGS="$CFLAGS -Wno-strict-prototypes"
 	fi
 
+	if [ "$os" = "OPENBSD" ]; then
+		LIBS="$LIBS -pthread"
+	fi
+
 	if [ "$os" = "OSX" ]; then
 		LDFLAGS="$LDFLAGS -framework Cocoa"
 		if [ "$enable_dedicated" = "0" ]; then
@@ -767,7 +771,7 @@
 	fi
 
 	# Most targets act like UNIX, just with some additions
-	if [ "$os" = "BEOS" ] || [ "$os" = "OSX" ] || [ "$os" = "MORPHOS" ] || [ "$os" = "FREEBSD" ] || [ "$os" = "SUNOS" ] || [ "$os" = "OS2" ]; then
+	if [ "$os" = "BEOS" ] || [ "$os" = "OSX" ] || [ "$os" = "MORPHOS" ] || [ "$os" = "FREEBSD" ] || [ "$os" = "OPENBSD" ] || [ "$os" = "SUNOS" ] || [ "$os" = "OS2" ]; then
 		CFLAGS="$CFLAGS -DUNIX"
 	fi
 	# And others like Windows
@@ -1267,13 +1271,14 @@
 
 detect_os() {
 	if [ "$os" = "DETECT" ]; then
-		# Detect UNIX, OSX, FREEBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP
+		# Detect UNIX, OSX, FREEBSD, OPENBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP
 
 		# Try first via dumpmachine, then via uname
 		os=`echo "$host" | tr '[A-Z]' '[a-z]' | $awk '
 					/linux/        { print "UNIX";    exit}
 					/darwin/       { print "OSX";     exit}
 					/freebsd/      { print "FREEBSD"; exit}
+					/openbsd/      { print "OPENBSD"; exit}
 					/morphos/      { print "MORPHOS"; exit}
 					/beos/         { print "BEOS";    exit}
 					/sunos/        { print "SUNOS";   exit}
@@ -1290,6 +1295,7 @@
 					/linux/        { print "UNIX";    exit}
 					/darwin/       { print "OSX";     exit}
 					/freebsd/      { print "FREEBSD"; exit}
+					/openbsd/      { print "OPENBSD"; exit}
 					/morphos/      { print "MORPHOS"; exit}
 					/beos/         { print "BEOS";    exit}
 					/sunos/        { print "SUNOS";   exit}
@@ -1301,8 +1307,8 @@
 
 		if [ -z "$os" ]; then
 			log 1 "detecting OS... none detected"
-			log 1 "I couldn't detect your OS. Please use --with-os=OS to force one"
-			log 1 "Allowed values are: UNIX, OSX, FREEBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP"
+			log 1 "I couldn't detect your OS. Please use --os=OS to force one"
+			log 1 "Allowed values are: UNIX, OSX, FREEBSD, OPENBSD, MORPHOS, BEOS, SUNOS, CYGWIN, MINGW, OS2, WINCE, and PSP"
 			exit 1
 		fi
 
@@ -2010,8 +2016,8 @@
 	echo "  --awk=AWK                      the awk to use in configure [awk]"
 	echo "  --lipo=LIPO                    the lipo to use (OSX ONLY) [HOST-lipo]"
 	echo "  --os=OS                        the OS we are compiling for [DETECT]"
-	echo "                                 DETECT/UNIX/OSX/FREEBSD/MORPHOS/BEOS/"
-	echo "                                 SUNOS/CYGWIN/MINGW/OS2/WINCE/PSP"
+	echo "                                 DETECT/UNIX/OSX/FREEBSD/OPENBSD/MORPHOS/"
+	echo "                                 BEOS/SUNOS/CYGWIN/MINGW/OS2/WINCE/PSP"
 	echo "  --endian=ENDIAN                set the endian of the HOST (AUTO/LE/BE)"
 	echo "  --revision=rXXXX               overwrite the revision detection."
 	echo "                                 Use with care!"
--- a/docs/landscape.html	Fri May 11 15:13:08 2007 +0000
+++ b/docs/landscape.html	Fri May 25 00:25:08 2007 +0000
@@ -475,9 +475,9 @@
    <td valign=top nowrap>&nbsp;</td>
    <td>
     <ul>
-     <li>m5 bits 7..4 clear: road
+     <li>m5 bits 7..6 clear: road
       <ul>
-       <li>m1: <a href="#OwnershipInfo">owner</a> of the road</li>
+       <li>m1: <a href="#OwnershipInfo">owner</a> of the road type #1</li>
        <li>m2: Index into the array of towns, 0 for non-town roads</li>
        <li>m3 bit 7 set = on snow or desert</li>
        <li>m3 bits 6..4:
@@ -513,7 +513,7 @@
         </table>
        </li>
        <li>m3 bits 3..0: counter for the roadworks</li>
-       <li>m5 bits 3..0: road layout: bit set = road piece present:
+       <li>m4 bits 3..0: road layout road type #1: bit set = road piece present:
         <table>
          <tr>
           <td nowrap valign=top>bit 0: </td>
@@ -533,25 +533,35 @@
          </tr>
         </table>
        </li>
+       <li>m4 bits 7..4: road layout road type #2
+       <li>m5 bits 4..0: owner of road type #2
+       <li>m6 bits 5..2: road layout road type #3
+       <li>m7 bits 7..5: road types
+       <li>m7 bits 4..0: owner of road type #3
+       </li>
       </ul>
      </li>
-     <li>m5 bit 5 set: road depot
+     <li>m5 bit 7 set, bit 6 clear: road depot
       <ul>
        <li>m1: <a href="#OwnershipInfo">owner</a> of the depot</li>
        <li>m3 bit 7 set = on snow or desert (not displayed, but set internally)</li>
        <li>m5 bits 3..0 - direction: exit towards: <tt>0</tt> = NE, <tt>1</tt> = SE, <tt>2</tt> = SW, <tt>3</tt> = NW</li>
+       <li>m7 bits 7..5: road types
       </ul>
      </li>
-     <li>m5 bit 4 set, bits 7..5 clear: level crossing
+     <li>m5 bit 6 set, bit 7 clear: level crossing
       <ul>
        <li>m1: <a href="#OwnershipInfo">owner</a> of the railway track</li>
        <li>m2: Index into the array of towns, 0 for non-town roads</li>
        <li>m3 bit 7 set = on snow or desert</li>
        <li>m3 bits 6..4: <tt>0</tt> - on bare land, <tt>1</tt> - on grass, <tt>2</tt> or higher - paved</li>
        <li>m3 bits 3..0: <a href="#TrackType">track type</a></li>
-       <li>m4: <a href="#OwnershipInfo">owner</a> of the road</li>
-       <li>m5 bit 3: clear - road in the X direction, set - road in the Y direction (railway track always perpendicular)</li>
-       <li>m5 bit 2: set if crossing lights are on</li>
+       <li>m4 bit 6: clear - road in the X direction, set - road in the Y direction (railway track always perpendicular)</li>
+       <li>m4 bit 5: set if crossing lights are on</li>
+       <li>m4 bits 4..0: <a href="#OwnershipInfo">owner</a> of the road type #1</li>
+       <li>m5 bits 4..0: owner of road type #2
+       <li>m7 bits 7..5: road types
+       <li>m7 bits 4..0: owner of road type #3
       </ul>
      </li>
      <li>m6 bits 7..6 : Possibility of a bridge above, in the <a href="#bridge_direction">direction specified</a></li>
--- a/docs/landscape_grid.html	Fri May 11 15:13:08 2007 +0000
+++ b/docs/landscape_grid.html	Fri May 25 00:25:08 2007 +0000
@@ -123,11 +123,11 @@
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX XXXX XXXX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span></td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits">XX<span class="free">OO OO</span>XX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span></td>
+      <td class="bits">XX<span class="free">OO</span> XXXX</td>
+      <td class="bits">XXXX XXXX</td>
+      <td class="bits">XXXX XXXX</td>
     </tr>
     <tr>
       <td class="caption">level crossing</td>
@@ -135,10 +135,10 @@
       <td class="bits">-inherit-</td>
       <td class="bits">-inherit-</td>
       <td class="bits">XXXX XXXX</td>
+      <td class="bits"><span class="free">O</span>XXX XXXX</td>
+      <td class="bits">XX<span class="free">OO</span> XXXX</td>
+      <td class="bits">XX<span class="free">OO OO</span>XX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits">XXXX XX<span class="free">OO</span></td>
-      <td class="bits">XX<span class="free">OO OO</span>XX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span></td>
     </tr>
     <tr>
       <td class="caption">road depot</td>
@@ -147,9 +147,9 @@
       <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
       <td class="bits">X<span class="free">OOO OOOO</span></td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
-      <td class="bits">XXXX XXXX</td>
+      <td class="bits">XX<span class="free">OO</span> XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span></td>
+      <td class="bits">XXX<span class="free">O OOOO</span></td>
     </tr>
     <tr>
       <td>3</td>
--- a/projects/openttd.vcproj	Fri May 11 15:13:08 2007 +0000
+++ b/projects/openttd.vcproj	Fri May 25 00:25:08 2007 +0000
@@ -459,6 +459,9 @@
 				RelativePath=".\..\src\gfxinit.h">
 			</File>
 			<File
+				RelativePath=".\..\src\group.h">
+			</File>
+			<File
 				RelativePath=".\..\src\gui.h">
 			</File>
 			<File
@@ -525,6 +528,9 @@
 				RelativePath=".\..\src\newgrf_cargo.h">
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_commons.h">
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_config.h">
 			</File>
 			<File
@@ -680,6 +686,9 @@
 			<File
 				RelativePath=".\..\src\window.h">
 			</File>
+			<File
+				RelativePath=".\..\src\zoom.hpp">
+			</File>
 		</Filter>
 		<Filter
 			Name="GUI Source Code"
@@ -715,6 +724,9 @@
 				RelativePath=".\..\src\graph_gui.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\group_gui.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\industry_gui.cpp">
 			</File>
 			<File
@@ -803,6 +815,9 @@
 				RelativePath=".\..\src\dummy_land.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\group_cmd.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\industry_cmd.cpp">
 			</File>
 			<File
@@ -1203,6 +1218,9 @@
 				RelativePath=".\..\src\newgrf_cargo.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_commons.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_config.cpp">
 			</File>
 			<File
--- a/projects/openttd_vs80.vcproj	Fri May 11 15:13:08 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Fri May 25 00:25:08 2007 +0000
@@ -840,6 +840,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\group.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\gui.h"
 				>
 			</File>
@@ -928,6 +932,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_commons.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_config.h"
 				>
 			</File>
@@ -1135,6 +1143,10 @@
 				RelativePath=".\..\src\window.h"
 				>
 			</File>
+			<File
+				RelativePath=".\..\src\zoom.hpp"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="GUI Source Code"
@@ -1180,6 +1192,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\group_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\industry_gui.cpp"
 				>
 			</File>
@@ -1296,6 +1312,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\group_cmd.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\industry_cmd.cpp"
 				>
 			</File>
@@ -1820,6 +1840,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\newgrf_commons.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\newgrf_config.cpp"
 				>
 			</File>
--- a/readme.txt	Fri May 11 15:13:08 2007 +0000
+++ b/readme.txt	Fri May 25 00:25:08 2007 +0000
@@ -75,6 +75,7 @@
   Linux                - SDL
   MacOS X (universal)  - Cocoa video and sound drivers (SDL works too, but not 100% and not as a universal binary)
   MorphOS              - SDL
+  OpenBSD              - SDL
   OS/2                 - SDL
   Windows              - Win32 GDI (faster) or SDL
 
@@ -174,6 +175,10 @@
   graphics/png is optional for screenshots in the PNG format.
   Use "gmake", but do a "./configure" before the first build.
 
+OpenBSD:
+  Use "gmake", but do a "./configure" before the first build.
+  Note that you need the port devel/sdl to compile OpenTTD.
+
 MorphOS:
   Use "make". However, for the first build one has to do a "./configure" first.
   Note that you need the MorphOS SDK, latest libnix updates (else C++ parts of
--- a/source.list	Fri May 11 15:13:08 2007 +0000
+++ b/source.list	Fri May 25 00:25:08 2007 +0000
@@ -120,6 +120,7 @@
 genworld.h
 gfx.h
 gfxinit.h
+group.h
 gui.h
 hal.h
 heightmap.h
@@ -142,6 +143,7 @@
 newgrf_callbacks.h
 newgrf_canal.h
 newgrf_cargo.h
+newgrf_commons.h
 newgrf_config.h
 newgrf_engine.h
 newgrf_house.h
@@ -194,6 +196,7 @@
 sound/win32_s.h
 video/win32_v.h
 window.h
+zoom.hpp
 
 # GUI Source Code
 aircraft_gui.cpp
@@ -206,6 +209,7 @@
 engine_gui.cpp
 genworld_gui.cpp
 graph_gui.cpp
+group_gui.cpp
 industry_gui.cpp
 intro_gui.cpp
 main_gui.cpp
@@ -236,6 +240,7 @@
 clear_cmd.cpp
 disaster_cmd.cpp
 dummy_land.cpp
+group_cmd.cpp
 industry_cmd.cpp
 misc_cmd.cpp
 order_cmd.cpp
@@ -376,6 +381,7 @@
 newgrf.cpp
 newgrf_canal.cpp
 newgrf_cargo.cpp
+newgrf_commons.cpp
 newgrf_config.cpp
 newgrf_engine.cpp
 newgrf_house.cpp
--- a/src/ai/api/ai_order.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/ai/api/ai_order.cpp	Fri May 25 00:25:08 2007 +0000
@@ -7,7 +7,7 @@
 #include "ai_vehicle.hpp"
 #include "../../command.h"
 #include "../../order.h"
-
+#include "../../vehicle.h"
 #include "../../depot.h"
 #include "../../landscape.h"
 #include "../../rail_map.h"
--- a/src/ai/api/ai_road.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/ai/api/ai_road.cpp	Fri May 25 00:25:08 2007 +0000
@@ -48,8 +48,8 @@
 	/* Tiles not neighbouring */
 	if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
 
-	RoadBits r1 = ::GetAnyRoadBits(t1);
-	RoadBits r2 = ::GetAnyRoadBits(t2);
+	RoadBits r1 = ::GetAnyRoadBits(t1, ROADTYPE_ROAD);
+	RoadBits r2 = ::GetAnyRoadBits(t2, ROADTYPE_ROAD);
 
 	DiagDirection dir_1 = (DiagDirection)((::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3));
 	DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
@@ -101,7 +101,7 @@
 	if (TileX(start) != TileX(end) &&
 			TileY(start) != TileY(end)) return false;
 
-	return this->DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2), CMD_BUILD_LONG_ROAD);
+	return this->DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_BUILD_LONG_ROAD);
 }
 
 bool AIRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
@@ -111,7 +111,7 @@
 
 	uint entrance_dir = (TileX(tile) == TileX(front)) ? (TileY(tile) < TileY(front) ? 1 : 3) : (TileX(tile) < TileX(front) ? 2 : 0);
 
-	return this->DoCommand(tile, entrance_dir, 0, CMD_BUILD_ROAD_DEPOT);
+	return this->DoCommand(tile, entrance_dir, ROADTYPE_ROAD << 2, CMD_BUILD_ROAD_DEPOT);
 }
 
 bool AIRoad::BuildRoadStation(TileIndex tile, TileIndex front, bool truck, bool drive_through)
@@ -126,7 +126,7 @@
 		entrance_dir = (TileX(tile) == TileX(front)) ? (TileY(tile) < TileY(front) ? 1 : 3) : (TileX(tile) < TileX(front) ? 2 : 0);
 	}
 
-	return this->DoCommand(tile, entrance_dir, (drive_through ? 2 : 0) | (truck ? 1 : 0), CMD_BUILD_ROAD_STOP);
+	return this->DoCommand(tile, entrance_dir, (drive_through ? 2 : 0) | (truck ? 1 : 0) | (ROADTYPES_ROAD << 2), CMD_BUILD_ROAD_STOP);
 }
 
 bool AIRoad::RemoveRoad(TileIndex start, TileIndex end)
@@ -137,7 +137,7 @@
 	if (TileX(start) != TileX(end) &&
 			TileY(start) != TileY(end)) return false;
 
-	return this->DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2), CMD_REMOVE_LONG_ROAD);
+	return this->DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_REMOVE_LONG_ROAD);
 }
 
 bool AIRoad::RemoveRoadDepot(TileIndex tile)
--- a/src/ai/api/ai_vehicle.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/ai/api/ai_vehicle.cpp	Fri May 25 00:25:08 2007 +0000
@@ -5,10 +5,10 @@
 #include "ai_vehicle.hpp"
 #include "ai_cargo.hpp"
 #include "../../command.h"
+#include "../../vehicle.h"
 #include "../../depot.h"
 #include "../../engine.h"
 #include "../../player.h"
-#include "../../vehicle.h"
 
 /* static */ bool AIVehicle::IsValidEngine(EngineID engine_id)
 {
--- a/src/aircraft_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/aircraft_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -719,6 +719,7 @@
 	if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
 //		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
 //		v->u.air.targetairport = st->index;
+		if (v->current_order.type == OT_LOADING) v->LeaveStation();
 		v->current_order.type = OT_GOTO_DEPOT;
 		v->current_order.flags = OF_NON_STOP;
 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
@@ -1683,7 +1684,7 @@
 	/* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed
 	 * unless it is due for renewal but the engine is no longer available */
 	if (v->owner == _local_player && (
-				EngineHasReplacementForPlayer(p, v->engine_type) ||
+				EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) ||
 				((p->engine_renew && v->age - v->max_age > p->engine_renew_months * 30) &&
 				HASBIT(GetEngine(v->engine_type)->player_avail, _local_player))
 			)) {
@@ -1741,7 +1742,7 @@
 	if (v->current_order.type != OT_GOTO_DEPOT && v->owner == _local_player) {
 		/* only the vehicle owner needs to calculate the rest (locally) */
 		const Player* p = GetPlayer(v->owner);
-		if (EngineHasReplacementForPlayer(p, v->engine_type) ||
+		if (EngineHasReplacementForPlayer(p, v->engine_type, v->group_id) ||
 			(p->engine_renew && v->age - v->max_age > (p->engine_renew_months * 30))) {
 			/* send the aircraft to the hangar at next airport */
 			_current_player = _local_player;
--- a/src/aircraft_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/aircraft_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -393,6 +393,6 @@
 
 	if (w != NULL) {
 		w->caption_color = v->owner;
-		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
+		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), ZOOM_LVL_AIRCRAFT);
 	}
 }
--- a/src/airport_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/airport_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -34,12 +34,12 @@
 
 static void PlaceAirport(TileIndex tile)
 {
-	DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
+	DoCommandP(tile, _selected_airport_type, _ctrl_pressed, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
 }
 
 static void PlaceAir_DemolishArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, 4);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
 }
 
 
@@ -91,11 +91,11 @@
 		break;
 
 	case WE_PLACE_DRAG:
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		break;
 
 	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1) {
+		if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
 			DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
 		}
 		break;
--- a/src/autoreplace_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/autoreplace_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -16,6 +16,7 @@
 #include "train.h"
 #include "aircraft.h"
 #include "cargotype.h"
+#include "group.h"
 
 
 /*
@@ -136,7 +137,18 @@
 	char vehicle_name[32];
 	CargoID replacement_cargo_type;
 
-	new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type);
+	/* If the vehicle belongs to a group, check if the group is protected from the global autoreplace.
+	 *  If not, chek if an global auto replacement is defined */
+	new_engine_type = (IsValidGroupID(old_v->group_id) && GetGroup(old_v->group_id)->replace_protection) ?
+			INVALID_ENGINE :
+			EngineReplacementForPlayer(p, old_v->engine_type, DEFAULT_GROUP);
+
+	/* If we don't set new_egnine_type previously, we try to check if an autoreplacement was defined
+	 *  for the group and the engine_type of the vehicle */
+	if (new_engine_type == INVALID_ENGINE && !IsDefaultGroupID(old_v->group_id)) {
+		new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type, old_v->group_id);
+	}
+
 	if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type;
 
 	replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type);
@@ -194,6 +206,7 @@
 			new_v->profit_this_year = old_v->profit_this_year;
 			new_v->profit_last_year = old_v->profit_last_year;
 			new_v->service_interval = old_v->service_interval;
+			DoCommand(0, old_v->group_id, new_v->index, flags, CMD_ADD_VEHICLE_GROUP);
 			new_front = true;
 			new_v->unitnumber = old_v->unitnumber; // use the same unit number
 			new_v->dest_tile  = old_v->dest_tile;
@@ -211,6 +224,10 @@
 				if (temp_v != NULL) {
 					DoCommand(0, (new_v->index << 16) | temp_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
 				}
+			} else if (!IsDefaultGroupID(old_v->group_id) && IsValidGroupID(old_v->group_id)) {
+				/* Increase the new num engines of the group for the ships, aircraft, and road vehicles
+					The old new num engine is decrease in the destroyvehicle function */
+				GetGroup(old_v->group_id)->num_engines[new_v->engine_type]++;
 			}
 		}
 		/* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */
@@ -305,8 +322,17 @@
 			if (!p->engine_renew ||
 					w->age - w->max_age < (p->engine_renew_months * 30) || // replace if engine is too old
 					w->max_age == 0) { // rail cars got a max age of 0
-				if (!EngineHasReplacementForPlayer(p, w->engine_type)) // updates to a new model
+				/* If the vehicle belongs to a group, check if the group is protected from the global autoreplace.
+				   If not, chek if an global auto remplacement is defined */
+				if (IsValidGroupID(w->group_id)) {
+					if (!EngineHasReplacementForPlayer(p, w->engine_type, w->group_id) && (
+							GetGroup(w->group_id)->replace_protection ||
+							!EngineHasReplacementForPlayer(p, w->engine_type, DEFAULT_GROUP))) {
+						continue;
+					}
+				} else if (!EngineHasReplacementForPlayer(p, w->engine_type, DEFAULT_GROUP)) {
 					continue;
+				}
 			}
 
 			/* Now replace the vehicle */
--- a/src/autoreplace_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/autoreplace_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -14,6 +14,7 @@
 #include "variables.h"
 #include "vehicle_gui.h"
 #include "newgrf_engine.h"
+#include "group.h"
 
 
 static RailType _railtype_selected_in_replace_gui;
@@ -62,7 +63,7 @@
 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
  * @param type The type of engine
  */
-void AddRemoveEngineFromAutoreplaceAndBuildWindows(byte type)
+void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
 {
 	_rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable
 	_rebuild_right_list = true;
@@ -150,8 +151,11 @@
 		if (type == VEH_TRAIN && !GenerateReplaceRailList(e, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains
 
 		if (draw_left) {
+			const GroupID selected_group = WP(w, replaceveh_d).sel_group;
+			const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[e] : GetGroup(selected_group)->num_engines[e];
+
 			/* Skip drawing the engines we don't have any of and haven't set for replacement */
-			if (p->num_engines[e] == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e) == INVALID_ENGINE) continue;
+			if (num_engines == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e, selected_group) == INVALID_ENGINE) continue;
 		} else {
 			/* This is for engines we can replace to and they should depend on what we selected to replace from */
 			if (!IsEngineBuildable(e, type, _local_player)) continue; // we need to be able to build the engine
@@ -202,7 +206,7 @@
 }
 
 
-void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count);
+void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
 
 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
 {
@@ -231,6 +235,7 @@
 
 			Player *p = GetPlayer(_local_player);
 			EngineID selected_id[2];
+			const GroupID selected_group = WP(w,replaceveh_d).sel_group;
 
 			selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
 			selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
@@ -242,15 +247,15 @@
 			SetWindowWidgetDisabledState(w, 4,
 										 selected_id[0] == INVALID_ENGINE ||
 										 selected_id[1] == INVALID_ENGINE ||
-										 EngineReplacementForPlayer(p, selected_id[1]) != INVALID_ENGINE ||
-										 EngineReplacementForPlayer(p, selected_id[0]) == selected_id[1]);
+										 EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE ||
+										 EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]);
 
 			/* Disable the "Stop Replacing" button if:
 			 *   The left list (existing vehicle) is empty
 			 *   or The selected vehicle has no replacement set up */
 			SetWindowWidgetDisabledState(w, 6,
 										 selected_id[0] == INVALID_ENGINE ||
-										 !EngineHasReplacementForPlayer(p, selected_id[0]));
+										 !EngineHasReplacementForPlayer(p, selected_id[0], selected_group));
 
 			/* now the actual drawing of the window itself takes place */
 			SetDParam(0, _vehicle_type_names[w->window_number]);
@@ -277,10 +282,10 @@
 
 			/* sets up the string for the vehicle that is being replaced to */
 			if (selected_id[0] != INVALID_ENGINE) {
-				if (!EngineHasReplacementForPlayer(p, selected_id[0])) {
+				if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) {
 					SetDParam(0, STR_NOT_REPLACING);
 				} else {
-					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0])));
+					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0], selected_group)));
 				}
 			} else {
 				SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
@@ -296,7 +301,7 @@
 				EngineID end    = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list));
 
 				/* Do the actual drawing */
-				DrawEngineList(w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0);
+				DrawEngineList((VehicleType)w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0, selected_group);
 
 				/* Also draw the details if an engine is selected */
 				if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
@@ -328,12 +333,12 @@
 				case 4: { /* Start replacing */
 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
 					EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
-					DoCommandP(0, 3, veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
+					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
 				} break;
 
 				case 6: { /* Stop replacing */
 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
-					DoCommandP(0, 3, veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
+					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
 				} break;
 
 				case 7:
@@ -480,7 +485,7 @@
 };
 
 
-void ShowReplaceVehicleWindow(byte vehicletype)
+void ShowReplaceVehicleWindow(VehicleType vehicletype)
 {
 	Window *w;
 
@@ -509,4 +514,37 @@
 
 	w->caption_color = _local_player;
 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
+	WP(w, replaceveh_d).sel_group = DEFAULT_GROUP;
+ }
+
+void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
+{
+	Window *w;
+
+	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
+
+	switch (vehicletype) {
+		default: NOT_REACHED();
+		case VEH_TRAIN:
+			w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 8;
+			w->resize.step_height = 14;
+			WP(w, replaceveh_d).wagon_btnstate = true;
+			break;
+		case VEH_ROAD:
+			w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 8;
+			w->resize.step_height = 14;
+			break;
+		case VEH_SHIP:
+		case VEH_AIRCRAFT:
+			w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype);
+			w->vscroll.cap  = 4;
+			w->resize.step_height = 24;
+			break;
+	}
+
+	w->caption_color = _local_player;
+	WP(w, replaceveh_d).sel_group = id_g;
+	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
 }
--- a/src/bridge_map.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/bridge_map.h	Fri May 25 00:25:08 2007 +0000
@@ -211,7 +211,6 @@
 	SETBIT(_m[t].m6, 6 + a);
 }
 
-
 /**
  * Generic part to make a bridge ramp for both roads and rails.
  * @param t          the tile to make a bridge ramp
@@ -219,13 +218,15 @@
  * @param bridgetype the type of bridge this bridge ramp belongs to
  * @param d          the direction this ramp must be facing
  * @param tt         the transport type of the bridge
+ * @param rt         the road or rail type
  * @note this function should not be called directly.
  */
-static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt)
+static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt, uint rt)
 {
 	SetTileType(t, MP_TUNNELBRIDGE);
 	SetTileOwner(t, o);
 	_m[t].m2 = bridgetype << 4;
+	_m[t].m3 = rt;
 	_m[t].m4 = 0;
 	_m[t].m5 = 1 << 7 | tt << 2 | d;
 }
@@ -236,11 +237,11 @@
  * @param o          the new owner of the bridge ramp
  * @param bridgetype the type of bridge this bridge ramp belongs to
  * @param d          the direction this ramp must be facing
+ * @param r          the road type of the bridge
  */
-static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d)
+static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RoadTypes r)
 {
-	MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD);
-	_m[t].m3 = 0;
+	MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, r);
 }
 
 /**
@@ -253,8 +254,7 @@
  */
 static inline void MakeRailBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RailType r)
 {
-	MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL);
-	_m[t].m3 = r;
+	MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL, r);
 }
 
 
--- a/src/build_vehicle_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/build_vehicle_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -27,6 +27,7 @@
 #include "date.h"
 #include "strings.h"
 #include "cargotype.h"
+#include "group.h"
 
 
 enum BuildVehicleWidgets {
@@ -386,7 +387,7 @@
 	/* Wagon weight - (including cargo) */
 	uint weight = GetEngineProperty(engine_number, 0x16, rvi->weight);
 	SetDParam(0, weight);
-	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * rvi->capacity >> 4) + weight);
+	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight);
 	DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, 0);
 	y += 10;
 
@@ -461,7 +462,7 @@
 
 	/* Cargo type + capacity */
 	SetDParam(0, rvi->cargo_type);
-	SetDParam(1, rvi->capacity);
+	SetDParam(1, GetEngineProperty(engine_number, 0x0F, rvi->capacity));
 	SetDParam(2, refittable ? STR_9842_REFITTABLE : STR_EMPTY);
 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
 	y += 10;
@@ -480,7 +481,7 @@
 
 	/* Cargo type + capacity */
 	SetDParam(0, svi->cargo_type);
-	SetDParam(1, svi->capacity);
+	SetDParam(1, GetEngineProperty(engine_number, 0x0D, svi->capacity));
 	SetDParam(2, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
 	DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
 	y += 10;
@@ -543,10 +544,12 @@
 	bool refitable = false;
 
 	switch (e->type) {
+		default: NOT_REACHED();
 		case VEH_TRAIN: {
 			const RailVehicleInfo *rvi = RailVehInfo(engine_number);
+			uint capacity = GetEngineProperty(engine_number, 0x14, rvi->capacity);
 
-			refitable = (EngInfo(engine_number)->refit_mask != 0) && (rvi->capacity > 0);
+			refitable = (EngInfo(engine_number)->refit_mask != 0) && (capacity > 0);
 
 			if (rvi->railveh_type == RAILVEH_WAGON) {
 				y = DrawRailWagonPurchaseInfo(x, y, engine_number, rvi);
@@ -562,7 +565,7 @@
 				int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
 
 				SetDParam(0, rvi->cargo_type);
-				SetDParam(1, (rvi->capacity * (CountArticulatedParts(engine_number) + 1)) << multihead);
+				SetDParam(1, (capacity * (CountArticulatedParts(engine_number) + 1)) << multihead);
 				SetDParam(2, refitable ? STR_9842_REFITTABLE : STR_EMPTY);
 			}
 			DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
@@ -719,6 +722,7 @@
 	buildvehicle_d *bv = &WP(w, buildvehicle_d);
 
 	switch (bv->vehicle_type) {
+		default: NOT_REACHED();
 		case VEH_TRAIN:
 			GenerateBuildTrainList(w);
 			return; // trains should not reach the last sorting
@@ -756,7 +760,7 @@
  * @param selected_id what engine to highlight as selected, if any
  * @param show_count Display the number of vehicles (used by autoreplace)
  */
-void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count)
+void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
 {
 	byte step_size = GetVehicleListHeight(type);
 	byte x_offset = 0;
@@ -792,11 +796,12 @@
 
 	for (; min < max; min++, y += step_size) {
 		const EngineID engine = eng_list[min];
+		const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[engine] : GetGroup(selected_group)->num_engines[engine];
 
 		DrawString(x + x_offset, y, GetCustomEngineName(engine), engine == selected_id ? 0xC : 0x10);
-		DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && p->num_engines[engine] == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player));
+		DrawVehicleEngine(type, x, y + y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_player));
 		if (show_count) {
-			SetDParam(0, p->num_engines[engine]);
+			SetDParam(0, num_engines);
 			DrawStringRightAligned(213, y + (GetVehicleListHeight(type) == 14 ? 3 : 8), STR_TINY_BLACK, 0);
 		}
 	}
@@ -830,7 +835,7 @@
 	SetDParam(0, bv->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles
 	DrawWindowWidgets(w);
 
-	DrawEngineList(bv->vehicle_type, 2, 27, bv->eng_list, w->vscroll.pos, max, bv->sel_engine, false);
+	DrawEngineList(bv->vehicle_type, 2, 27, bv->eng_list, w->vscroll.pos, max, bv->sel_engine, false, DEFAULT_GROUP);
 
 	if (bv->sel_engine != INVALID_ENGINE) {
 		const Widget *wi = &w->widget[BUILD_VEHICLE_WIDGET_PANEL];
@@ -871,6 +876,7 @@
 			EngineID sel_eng = bv->sel_engine;
 			if (sel_eng != INVALID_ENGINE) {
 				switch (bv->vehicle_type) {
+					default: NOT_REACHED();
 					case VEH_TRAIN:
 						DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildLoco,
 								   CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
@@ -896,6 +902,7 @@
 
 				bv->rename_engine = sel_eng;
 				switch (bv->vehicle_type) {
+					default: NOT_REACHED();
 					case VEH_TRAIN:    str = STR_886A_RENAME_TRAIN_VEHICLE_TYPE; break;
 					case VEH_ROAD:     str = STR_9036_RENAME_ROAD_VEHICLE_TYPE;  break;
 					case VEH_SHIP:     str = STR_9838_RENAME_SHIP_TYPE;          break;
@@ -939,6 +946,7 @@
 				StringID str = STR_NULL;
 				_cmd_text = e->we.edittext.str;
 				switch (bv->vehicle_type) {
+					default: NOT_REACHED();
 					case VEH_TRAIN:    str = STR_886B_CAN_T_RENAME_TRAIN_VEHICLE; break;
 					case VEH_ROAD:     str = STR_9037_CAN_T_RENAME_ROAD_VEHICLE;  break;
 					case VEH_SHIP:     str = STR_9839_CAN_T_RENAME_SHIP_TYPE;     break;
@@ -976,7 +984,7 @@
 	NewVehicleWndProc
 };
 
-void ShowBuildVehicleWindow(TileIndex tile, byte type)
+void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
 {
 	buildvehicle_d *bv;
 	Window *w;
@@ -1005,6 +1013,7 @@
 	bv->descending_sort_order = _last_sort_order[type];
 
 	switch (type) {
+		default: NOT_REACHED();
 		case VEH_TRAIN:
 			WP(w, buildvehicle_d).filter.railtype = (tile == 0) ? RAILTYPE_END : GetRailType(tile);
 			ResizeWindow(w, 0, 16);
--- a/src/cargotype.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/cargotype.cpp	Fri May 25 00:25:08 2007 +0000
@@ -33,6 +33,14 @@
 	for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
 		CargoLabel cl = _default_climate_cargo[l][i];
 
+		/* Bzzt: check if cl is just an index into the cargo table */
+		if (cl < lengthof(_default_cargo)) {
+			/* Copy the indexed cargo */
+			_cargo[i] = _default_cargo[cl];
+			SETBIT(_cargo_mask, i);
+			continue;
+		}
+
 		/* Loop through each of the default cargo types to see if
 		 * the label matches */
 		for (uint j = 0; j < lengthof(_default_cargo); j++) {
--- a/src/clear_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/clear_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -764,7 +764,7 @@
 	/* not used */
 }
 
-static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	return 0;
 }
--- a/src/command.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/command.cpp	Fri May 25 00:25:08 2007 +0000
@@ -168,6 +168,14 @@
 DEF_COMMAND(CmdDepotSellAllVehicles);
 DEF_COMMAND(CmdDepotMassAutoReplace);
 
+DEF_COMMAND(CmdCreateGroup);
+DEF_COMMAND(CmdRenameGroup);
+DEF_COMMAND(CmdDeleteGroup);
+DEF_COMMAND(CmdAddVehicleGroup);
+DEF_COMMAND(CmdAddSharedVehicleGroup);
+DEF_COMMAND(CmdRemoveAllVehiclesGroup);
+DEF_COMMAND(CmdSetGroupReplaceProtection);
+
 /* The master command table */
 static const Command _command_proc_table[] = {
 	{CmdBuildRailroadTrack,                  0}, /*   0 */
@@ -313,6 +321,13 @@
 	{CmdMassStartStopVehicle,                0}, /* 117 */
 	{CmdDepotSellAllVehicles,                0}, /* 118 */
 	{CmdDepotMassAutoReplace,                0}, /* 119 */
+	{CmdCreateGroup,                         0}, /* 120 */
+	{CmdDeleteGroup,                         0}, /* 121 */
+	{CmdRenameGroup,                         0}, /* 122 */
+	{CmdAddVehicleGroup,                     0}, /* 123 */
+	{CmdAddSharedVehicleGroup,               0}, /* 124 */
+	{CmdRemoveAllVehiclesGroup,              0}, /* 125 */
+	{CmdSetGroupReplaceProtection,           0}, /* 126 */
 };
 
 /* This function range-checks a cmd, and checks if the cmd is not NULL */
@@ -339,7 +354,7 @@
 	CommandProc *proc;
 
 	/* Do not even think about executing out-of-bounds tile-commands */
-	if (tile >= MapSize()) {
+	if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
 		_cmd_text = NULL;
 		return CMD_ERROR;
 	}
@@ -417,7 +432,7 @@
 	int y = TileY(tile) * TILE_SIZE;
 
 	/* Do not even think about executing out-of-bounds tile-commands */
-	if (tile >= MapSize()) {
+	if (tile >= MapSize() || IsTileType(tile, MP_VOID)) {
 		_cmd_text = NULL;
 		return false;
 	}
--- a/src/command.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/command.h	Fri May 25 00:25:08 2007 +0000
@@ -143,6 +143,13 @@
 	CMD_MASS_START_STOP              = 117,
 	CMD_DEPOT_SELL_ALL_VEHICLES      = 118,
 	CMD_DEPOT_MASS_AUTOREPLACE       = 119,
+	CMD_CREATE_GROUP                 = 120,
+	CMD_DELETE_GROUP                 = 121,
+	CMD_RENAME_GROUP                 = 122,
+	CMD_ADD_VEHICLE_GROUP            = 123,
+	CMD_ADD_SHARED_VEHICLE_GROUP     = 124,
+	CMD_REMOVE_ALL_VEHICLES_GROUP    = 125,
+	CMD_SET_GROUP_REPLACE_PROTECTION = 126,
 };
 
 enum {
--- a/src/depot.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/depot.cpp	Fri May 25 00:25:08 2007 +0000
@@ -4,6 +4,7 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "vehicle.h"
 #include "depot.h"
 #include "functions.h"
 #include "landscape.h"
--- a/src/depot.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/depot.h	Fri May 25 00:25:08 2007 +0000
@@ -42,7 +42,7 @@
 	depot->xy = 0;
 }
 
-void ShowDepotWindow(TileIndex tile, byte type);
+void ShowDepotWindow(TileIndex tile, VehicleType type);
 
 #define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) if (IsValidDepot(d))
 #define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
--- a/src/depot_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/depot_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -137,6 +137,7 @@
 		case VEH_ROAD:     CcCloneRoadVeh( true, tile, p1, p2); break;
 		case VEH_SHIP:     CcCloneShip(    true, tile, p1, p2); break;
 		case VEH_AIRCRAFT: CcCloneAircraft(true, tile, p1, p2); break;
+		default: NOT_REACHED();
 	}
 }
 
@@ -656,7 +657,7 @@
 	_block_sizes[VEH_ROAD][1] = GetVehicleListHeight(VEH_ROAD);
 }
 
-static void ResizeDefaultWindowSize(byte type)
+static void ResizeDefaultWindowSize(VehicleType type)
 {
 	EngineID engine;
 	uint max_width  = 0;
@@ -696,7 +697,7 @@
 	ResizeDefaultWindowSize(VEH_AIRCRAFT);
 }
 
-static void CreateDepotListWindow(Window *w, byte type)
+static void CreateDepotListWindow(Window *w, VehicleType type)
 {
 	WP(w, depot_d).type = type;
 	_backup_orders_tile = 0;
@@ -974,7 +975,7 @@
  * @param tile The tile where the depot/hangar is located
  * @param type The type of vehicles in the depot
  */
-void ShowDepotWindow(TileIndex tile, byte type)
+void ShowDepotWindow(TileIndex tile, VehicleType type)
 {
 	Window *w;
 
--- a/src/disaster_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/disaster_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -713,7 +713,7 @@
 
 	tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
 	if (IsValidTile(tile)) {
-		TrackdirBits r = (TrackdirBits)GetTileTrackStatus(tile, TRANSPORT_WATER);
+		TrackdirBits r = (TrackdirBits)GetTileTrackStatus(tile, TRANSPORT_WATER, 0);
 
 		if (TrackdirBitsToTrackBits(r) == TRACK_BIT_ALL && !CHANCE16(1, 90)) {
 			GetNewVehiclePosResult gp = GetNewVehiclePos(v);
--- a/src/dock_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/dock_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -38,7 +38,7 @@
 
 static void PlaceDocks_Dock(TileIndex tile)
 {
-	DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
+	DoCommandP(tile, _ctrl_pressed, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
 }
 
 static void PlaceDocks_Depot(TileIndex tile)
@@ -53,12 +53,12 @@
 
 static void PlaceDocks_DemolishArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
 }
 
 static void PlaceDocks_BuildCanal(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_OR_Y);
+	VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_CREATE_WATER);
 }
 
 static void PlaceDocks_BuildLock(TileIndex tile)
@@ -147,16 +147,20 @@
 		break;
 
 	case WE_PLACE_DRAG: {
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		return;
 	}
 
 	case WE_PLACE_MOUSEUP:
 		if (e->we.place.pt.x != -1) {
-			if ((e->we.place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
-				GUIPlaceProcDragXY(e);
-			} else if (e->we.place.userdata == VPM_X_OR_Y) {
-				DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
+			switch (e->we.place.select_proc) {
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(e);
+					break;
+				case DDSP_CREATE_WATER:
+					DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
+					break;
+				default: break;
 			}
 		}
 		break;
--- a/src/dummy_land.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/dummy_land.cpp	Fri May 25 00:25:08 2007 +0000
@@ -63,7 +63,7 @@
 	/* not used */
 }
 
-static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Dummy(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	return 0;
 }
--- a/src/economy.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/economy.cpp	Fri May 25 00:25:08 2007 +0000
@@ -38,6 +38,7 @@
 #include "date.h"
 #include "cargotype.h"
 #include "player_face.h"
+#include "group.h"
 
 /* Score info */
 const ScoreInfo _score_info[] = {
@@ -359,12 +360,14 @@
 					DeleteVehicle(v);
 				} else {
 					v->owner = new_player;
+					v->group_id = DEFAULT_GROUP;
 					if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
 					switch (v->type) {
 						case VEH_TRAIN:    if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
 						case VEH_ROAD:     v->unitnumber = ++num_road; break;
 						case VEH_SHIP:     v->unitnumber = ++num_ship; break;
 						case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
+						default: NOT_REACHED();
 					}
 				}
 			}
@@ -955,6 +958,7 @@
 static void FindSubsidyCargoRoute(FoundRoute *fr)
 {
 	Industry *i;
+	const IndustrySpec *ind;
 	int trans, total;
 	CargoID cargo;
 
@@ -962,14 +966,15 @@
 
 	fr->from = i = GetRandomIndustry();
 	if (i == NULL) return;
+	ind = GetIndustrySpec(i->type);
 
 	/* Randomize cargo type */
-	if (Random()&1 && i->produced_cargo[1] != CT_INVALID) {
-		cargo = i->produced_cargo[1];
+	if (HASBIT(Random(), 0) && ind->produced_cargo[1] != CT_INVALID) {
+		cargo = ind->produced_cargo[1];
 		trans = i->pct_transported[1];
 		total = i->total_production[1];
 	} else {
-		cargo = i->produced_cargo[0];
+		cargo = ind->produced_cargo[0];
 		trans = i->pct_transported[0];
 		total = i->total_production[0];
 	}
@@ -996,13 +1001,19 @@
 	} else {
 		/* The destination is an industry */
 		Industry *i2 = GetRandomIndustry();
+		if (i2 == NULL) {
+			return;
+		}
+
+		ind = GetIndustrySpec(i2->type);
 
 		/* The industry must accept the cargo */
-		if (i == i2 || i == NULL ||
-				(cargo != i2->accepts_cargo[0] &&
-				cargo != i2->accepts_cargo[1] &&
-				cargo != i2->accepts_cargo[2]))
+		if (i == i2 ||
+				(cargo != ind->accepts_cargo[0] &&
+				cargo != ind->accepts_cargo[1] &&
+				cargo != ind->accepts_cargo[2])) {
 			return;
+		}
 		fr->distance = DistanceManhattan(i->xy, i2->xy);
 		fr->to = i2;
 	}
@@ -1176,34 +1187,48 @@
 
 static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces)
 {
-	Industry* best = NULL;
-	Industry* ind;
-	uint u;
+	Industry *best = NULL;
+	Industry *ind;
+	const IndustrySpec *indspec;
+	uint best_dist;
+	uint accepted_cargo_index = 0;  ///< unlikely value, just for warning removing
 
 	/* Check if there's an industry close to the station that accepts the cargo
 	 * XXX - Think of something better to
 	 *       1) Only deliver to industries which are withing the catchment radius
 	 *       2) Distribute between industries if more then one is present */
-	u = (_patches.station_spread + 8) * 2;
+	best_dist = (_patches.station_spread + 8) * 2;
 	FOR_ALL_INDUSTRIES(ind) {
-		uint t;
+		indspec = GetIndustrySpec(ind->type);
+		uint i;
 
-		if (( cargo_type == ind->accepts_cargo[0] ||
-					cargo_type == ind->accepts_cargo[1] ||
-					cargo_type == ind->accepts_cargo[2]
-				) &&
-				ind->produced_cargo[0] != CT_INVALID &&
-				ind->produced_cargo[0] != cargo_type &&
-				(t = DistanceManhattan(ind->xy, xy)) < u) {
-			u = t;
+		if (indspec->produced_cargo[0] == CT_INVALID) continue;
+
+		for (i = 0; i < lengthof(indspec->accepts_cargo); i++) {
+			if (cargo_type == indspec->accepts_cargo[i] &&
+					(indspec->input_cargo_multiplier[i][0] != 0 || indspec->input_cargo_multiplier[i][1] != 0)) {
+				break;
+			}
+		}
+
+		/* Check if matching cargo has been found */
+		if (i == lengthof(indspec->accepts_cargo)) continue;
+
+		uint dist = DistanceManhattan(ind->xy, xy);
+
+		if (dist < best_dist) {
 			best = ind;
+			best_dist = dist;
+			accepted_cargo_index = i;
 		}
 	}
 
 	/* Found one? */
 	if (best != NULL) {
+		indspec = GetIndustrySpec(best->type);
 		best->was_cargo_delivered = true;
-		best->cargo_waiting[0] = min(best->cargo_waiting[0] + num_pieces, 0xFFFF);
+		best->cargo_waiting[0] = min(best->cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
+		best->cargo_waiting[1] = min(best->cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
 	}
 }
 
@@ -1322,128 +1347,6 @@
 	return profit;
 }
 
-/*
- * Returns true if Vehicle v should wait loading because other vehicle is
- * already loading the same cargo type
- * v = vehicle to load, u = GetFirstInChain(v)
- */
-static bool LoadWait(const Vehicle* v, const Vehicle* u)
-{
-	const Vehicle *w;
-	bool has_any_cargo = false;
-
-	if (!(u->current_order.flags & OF_FULL_LOAD)) return false;
-
-	for (w = u; w != NULL; w = w->next) {
-		if (w->cargo_count != 0) {
-			if (v->cargo_type == w->cargo_type &&
-					u->last_station_visited == w->cargo_source) {
-				return false;
-			}
-			has_any_cargo = true;
-		}
-	}
-
-	const Station *st = GetStation(u->last_station_visited);
-	std::list<Vehicle *>::const_iterator iter;
-	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
-		const Vehicle *x = *iter;
-		if (!(x->vehstatus & (VS_STOPPED | VS_CRASHED)) && u != x) {
-			bool other_has_any_cargo = false;
-			bool has_space_for_same_type = false;
-			bool other_has_same_type = false;
-
-			for (w = x; w != NULL; w = w->next) {
-				if (w->cargo_count < w->cargo_cap && v->cargo_type == w->cargo_type) {
-					has_space_for_same_type = true;
-				}
-
-				if (w->cargo_count != 0) {
-					if (v->cargo_type == w->cargo_type &&
-							u->last_station_visited == w->cargo_source) {
-						other_has_same_type = true;
-					}
-					other_has_any_cargo = true;
-				}
-			}
-
-			if (has_space_for_same_type) {
-				if (other_has_same_type) return true;
-				if (other_has_any_cargo && !has_any_cargo) return true;
-			}
-		}
-	}
-
-	return false;
-}
-
-static bool CanFillVehicle_FullLoadAny(Vehicle *v)
-{
-	uint32 full = 0, not_full = 0;
-	const GoodsEntry *ge = GetStation(v->last_station_visited)->goods;
-
-	/* special handling of aircraft */
-
-	/* if the aircraft carries passengers and is NOT full, then
-	 *continue loading, no matter how much mail is in */
-	if (v->type == VEH_AIRCRAFT &&
-			IsCargoInClass(v->cargo_type, CC_PASSENGERS) &&
-			v->cargo_cap != v->cargo_count) {
-		return true;
-	}
-
-	/* patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded. */
-	do {
-		/* Should never happen, but just in case future additions change this */
-		assert(v->cargo_type<32);
-
-		if (v->cargo_cap != 0) {
-			uint32 mask = 1 << v->cargo_type;
-
-			if (!HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING) && v->cargo_cap == v->cargo_count) {
-				full |= mask;
-			} else if (GB(ge[v->cargo_type].waiting_acceptance, 0, 12) > 0 ||
-					(HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING) && (ge[v->cargo_type].waiting_acceptance & 0x8000))) {
-				/* If there is any cargo waiting, or this vehicle is still unloading
-				 * and the station accepts the cargo, don't leave the station. */
-				return true;
-			} else {
-				not_full |= mask;
-			}
-		}
-	} while ((v = v->next) != NULL);
-
-	/* continue loading if there is a non full cargo type and no cargo type that is full */
-	return not_full && (full & ~not_full) == 0;
-}
-
-
-static bool CanFillVehicle(Vehicle *front_v)
-{
-	TileIndex tile = front_v->tile;
-
-	assert(IsTileType(tile, MP_STATION) ||
-			(front_v->type == VEH_SHIP && (
-				IsTileType(TILE_ADDXY(tile,  1,  0), MP_STATION) ||
-				IsTileType(TILE_ADDXY(tile, -1,  0), MP_STATION) ||
-				IsTileType(TILE_ADDXY(tile,  0,  1), MP_STATION) ||
-				IsTileType(TILE_ADDXY(tile,  0, -1), MP_STATION) ||
-				IsTileType(TILE_ADDXY(tile, -2,  0), MP_STATION)
-			)));
-
-	bool full_load = HASBIT(front_v->current_order.flags, OFB_FULL_LOAD);
-
-	/* If patch is active, use alternative CanFillVehicle-function */
-	if (_patches.full_load_any && full_load) return CanFillVehicle_FullLoadAny(front_v);
-
-	Vehicle *v = front_v;
-	do {
-		if (HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING) || (full_load && v->cargo_count != v->cargo_cap)) return true;
-	} while ((v = v->next) != NULL);
-
-	return !HASBIT(front_v->vehicle_flags, VF_LOADING_FINISHED);
-}
-
 /**
  * Performs the vehicle payment _and_ marks the vehicle to be unloaded.
  * @param front_v the vehicle to be unloaded
@@ -1476,7 +1379,7 @@
 
 	for (Vehicle *v = front_v; v != NULL; v = v->next) {
 		/* No cargo to unload */
-		if (v->cargo_cap == 0) continue;
+		if (v->cargo_cap == 0 || v->cargo_count == 0) continue;
 
 		SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
 		/* All cargo has already been paid for, no need to pay again */
@@ -1547,114 +1450,119 @@
 /**
  * Loads/unload the vehicle if possible.
  * @param v the vehicle to be (un)loaded
- * @return true if something was (un)loaded. False if the train is ready to leave.
+ * @param cargo_left the amount of each cargo type that is
+ *                   virtually left on the platform to be
+ *                   picked up by another vehicle when all
+ *                   previous vehicles have loaded.
  */
-bool LoadUnloadVehicle(Vehicle *v)
+static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
 {
-	if (!CanFillVehicle(v)) return false;
+	assert(v->current_order.type == OT_LOADING);
 
-	int unloading_time = 20;
+	/* We have not waited enough time till the next round of loading/unloading */
+	if (--v->load_unload_time_rem != 0) {
+		if (_patches.improved_load && HASBIT(v->current_order.flags, OFB_FULL_LOAD)) {
+			/* 'Reserve' this cargo for this vehicle, because we were first. */
+			for (; v != NULL; v = v->next) {
+				if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+			}
+		}
+		return;
+	}
+
+	int unloading_time = 0;
 	Vehicle *u = v;
 	int result = 0;
-	int t;
-	uint count, cap;
+	int cap;
 
-	bool completely_empty = true;
-	byte load_amount;
-	bool anything_loaded = false;
+	bool completely_empty  = true;
+	bool anything_unloaded = false;
+	bool anything_loaded   = false;
+	uint32 cargo_not_full  = 0;
+	uint32 cargo_full      = 0;
 	int total_cargo_feeder_share = 0; // the feeder cash amount for the goods being loaded/unloaded in this load step
 
-	assert(v->current_order.type == OT_LOADING);
-
 	v->cur_speed = 0;
 
-	/* Loading can only have finished when all the cargo has been unloaded, and
-	 * there is nothing left to load. It's easier to clear this if the
-	 * conditions haven't been met than attempting to check them all before
-	 * enabling though. */
-	SETBIT(v->vehicle_flags, VF_LOADING_FINISHED);
-
 	StationID last_visited = v->last_station_visited;
 	Station *st = GetStation(last_visited);
 
 	for (; v != NULL; v = v->next) {
-		GoodsEntry* ge;
-		load_amount = EngInfo(v->engine_type)->load_amount;
+		if (v->cargo_cap == 0) continue;
+
+		byte load_amount = EngInfo(v->engine_type)->load_amount;
 		if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_LOAD_AMOUNT)) {
 			uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
 			if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF;
 		}
 
-		if (v->cargo_cap == 0) continue;
-
-		ge = &st->goods[v->cargo_type];
-		count = GB(ge->waiting_acceptance, 0, 12);
+		GoodsEntry *ge = &st->goods[v->cargo_type];
+		int count = GB(ge->waiting_acceptance, 0, 12);
 
-		/* unload? */
-		if (v->cargo_count != 0 && HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) {
+		if (HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) {
 			uint16 amount_unloaded = _patches.gradual_loading ? min(v->cargo_count, load_amount) : v->cargo_count;
 
-			CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
-
 			if (v->cargo_source != last_visited && ge->waiting_acceptance & 0x8000 && !(u->current_order.flags & OF_TRANSFER)) {
-				/* deliver goods to the station */
-				st->time_since_unload = 0;
-
-				unloading_time += v->cargo_count; // TTDBUG: bug in original TTD
-
 				result |= 1;
-				v->cargo_count -= amount_unloaded;
-				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
-				if (_patches.gradual_loading) continue;
-
 			} else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) {
-				/* unload goods and let it wait at the station */
-				st->time_since_unload = 0;
-
-				unloading_time += v->cargo_count;
-				t = GB(ge->waiting_acceptance, 0, 12);
-				if (t == 0) {
+				if (count == 0) {
 					/* No goods waiting at station */
-					ge->enroute_time = v->cargo_days;
-					ge->enroute_from = v->cargo_source;
+					ge->enroute_time    = v->cargo_days;
+					ge->enroute_from    = v->cargo_source;
 					ge->enroute_from_xy = v->cargo_source_xy;
 				} else {
 					/* Goods already waiting at station. Set counters to the worst value. */
 					if (v->cargo_days >= ge->enroute_time) ge->enroute_time = v->cargo_days;
 
 					if (last_visited != ge->enroute_from) {
-						ge->enroute_from = v->cargo_source;
+						ge->enroute_from    = v->cargo_source;
 						ge->enroute_from_xy = v->cargo_source_xy;
 					}
 				}
-				/* Update amount of waiting cargo */
-				SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + t, 0xFFF));
+				/* Update amount of waiting cargo. There is, however, no sense in
+				 * updating the count variable because this vehicle will not be
+				 * able to take the cargo. */
+				SB(ge->waiting_acceptance, 0, 12, min(amount_unloaded + count, 0xFFF));
 
 				/* if there is not enough to unload from pending, ensure it does not go -ve
 				 * else deduct amount actually unloaded from unload_pending */
 				SB(ge->unload_pending, 0, 12, max(GB(ge->unload_pending, 0, 12) - amount_unloaded, 0U));
 
 				result |= 2;
-				v->cargo_count -= amount_unloaded;
-				v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
-				if (_patches.gradual_loading) continue;
+			} else {
+				/* The order changed while unloading (unset unload/transfer) or the
+				 * station does not accept goods anymore. */
+				CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+				continue;
 			}
 
-			if (v->cargo_count != 0) completely_empty = false;
-		}
+			/* Deliver goods to the station */
+			st->time_since_unload = 0;
 
-		/* The vehicle must have been unloaded because it is either empty, or
-		 * the UNLOADING bit is already clear in v->vehicle_flags. */
-		CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+			unloading_time += amount_unloaded;
+
+			v->cargo_count -= amount_unloaded;
+			v->cargo_paid_for -= min(amount_unloaded, v->cargo_paid_for);
+
+			anything_unloaded = true;
+			if (_patches.gradual_loading && v->cargo_count != 0) {
+				completely_empty = false;
+			} else {
+				/* We have finished unloading (cargo count == 0) */
+				CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING);
+			}
+
+			continue;
+		}
 
 		/* We cannot have paid for more cargo than there is on board. */
 		assert(v->cargo_paid_for <= v->cargo_count);
 
-		/* don't pick up goods that we unloaded */
+		/* Do not pick up goods that we unloaded */
 		if (u->current_order.flags & OF_UNLOAD) continue;
 
 		/* update stats */
-		ge->days_since_pickup = 0;
+		int t;
 		switch (u->type) {
 			case VEH_TRAIN: t = u->u.rail.cached_max_speed; break;
 			case VEH_ROAD:  t = u->max_speed / 2;           break;
@@ -1662,6 +1570,7 @@
 		}
 
 		/* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
+		ge->days_since_pickup = 0;
 		ge->last_speed = min(t, 255);
 		ge->last_age = _cur_year - v->build_year;
 
@@ -1670,15 +1579,23 @@
 		if (count != 0 &&
 				(cap = v->cargo_cap - v->cargo_count) != 0) {
 
-			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
-
 			/* Skip loading this vehicle if another train/vehicle is already handling
 			 * the same cargo type at this station */
-			if (_patches.improved_load && (u->current_order.flags & OF_FULL_LOAD) && LoadWait(v,u)) {
-				CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
+			if (_patches.improved_load && cargo_left[v->cargo_type] < 0) {
+				SETBIT(cargo_not_full, v->cargo_type);
 				continue;
 			}
 
+			if (cap > count) cap = count;
+			if (_patches.gradual_loading) cap = min(cap, load_amount);
+			if (_patches.improved_load) {
+				/* Don't load stuff that is already 'reserved' for other vehicles */
+				cap = min(cargo_left[v->cargo_type], cap);
+				cargo_left[v->cargo_type] -= cap;
+			}
+
+			if (v->cargo_count == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
+
 			/* TODO: Regarding this, when we do gradual loading, we
 			 * should first unload all vehicles and then start
 			 * loading them. Since this will cause
@@ -1689,10 +1606,6 @@
 			completely_empty = false;
 			anything_loaded = true;
 
-			if (cap > count) cap = count;
-			if (_patches.gradual_loading) cap = min(cap, load_amount);
-			if (cap < count) CLRBIT(u->vehicle_flags, VF_LOADING_FINISHED);
-
 			/* cargoshare is proportioned by the amount due to unload
 			 * Otherwise, with gradual loading, 100% of credits would be taken immediately,
 			 * even if the cargo volume represents a tiny percent of the whole.
@@ -1717,25 +1630,54 @@
 			result |= 2;
 			st->last_vehicle_type = v->type;
 		}
+
+		if (v->cargo_count == v->cargo_cap) {
+			SETBIT(cargo_full, v->cargo_type);
+		} else {
+			SETBIT(cargo_not_full, v->cargo_type);
+		}
+	}
+
+	/* We update these variables here, so gradual loading still fills
+	 * all wagons at the same time instead of using the same 'improved'
+	 * loading algorithm for the wagons (only fill wagon when there is
+	 * enough to fill the previous wagons) */
+	if (_patches.improved_load && HASBIT(u->current_order.flags, OFB_FULL_LOAD)) {
+		/* Update left cargo */
+		for (v = u; v != NULL; v = v->next) {
+			if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo_count;
+		}
 	}
 
 	v = u;
 
 	v->cargo_feeder_share += total_cargo_feeder_share;
 
-	if (_patches.gradual_loading) {
-		/* The time it takes to load one 'slice' of cargo or passengers depends
-		 * on the vehicle type - the values here are those found in TTDPatch */
-		uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
+	if (anything_loaded || anything_unloaded) {
+		if (_patches.gradual_loading) {
+			/* The time it takes to load one 'slice' of cargo or passengers depends
+			* on the vehicle type - the values here are those found in TTDPatch */
+			const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
 
-		unloading_time = gradual_loading_wait_time[v->type];
-		if (HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) {
-			if (anything_loaded) {
-				unloading_time += 20;
-			} else {
-				unloading_time = 20;
+			unloading_time = gradual_loading_wait_time[v->type];
+		}
+	} else {
+		bool finished_loading = true;
+		if (HASBIT(v->current_order.flags, OFB_FULL_LOAD)) {
+			if (_patches.full_load_any) {
+				/* if the aircraft carries passengers and is NOT full, then
+				 * continue loading, no matter how much mail is in */
+				if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap != v->cargo_count) ||
+						(cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos
+					finished_loading = false;
+				}
+			} else if (cargo_not_full != 0) {
+				finished_loading = false;
 			}
 		}
+		unloading_time = 20;
+
+		SB(v->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
 	}
 
 	if (v->type == VEH_TRAIN) {
@@ -1762,8 +1704,24 @@
 
 		if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
 	}
+}
 
-	return true;
+/**
+ * Load/unload the vehicles in this station according to the order
+ * they entered.
+ * @param st the station to do the loading/unloading for
+ */
+void LoadUnloadStation(Station *st)
+{
+	int cargo_left[NUM_CARGO];
+
+	for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = GB(st->goods[i].waiting_acceptance, 0, 12);
+
+	std::list<Vehicle *>::iterator iter;
+	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
+		Vehicle *v = *iter;
+		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
+	}
 }
 
 void PlayersMonthlyLoop()
--- a/src/economy.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/economy.h	Fri May 25 00:25:08 2007 +0000
@@ -69,5 +69,6 @@
 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount);
 
 void VehiclePayment(Vehicle *front_v);
+void LoadUnloadStation(Station *st);
 
 #endif /* ECONOMY_H */
--- a/src/engine.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/engine.cpp	Fri May 25 00:25:08 2007 +0000
@@ -20,6 +20,7 @@
 #include "newgrf_cargo.h"
 #include "date.h"
 #include "table/engines.h"
+#include "group.h"
 
 EngineInfo _engine_info[TOTAL_NUM_ENGINES];
 RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
@@ -70,6 +71,16 @@
 {
 	uint age = e->age;
 
+	/* Check for early retirement */
+	if (e->player_avail != 0 && !_patches.never_expire_vehicles) {
+		uint retire_early = EngInfo(e - _engines)->retire_early;
+		if (retire_early > 0 && age >= e->duration_phase_1 + e->duration_phase_2 - retire_early * 12) {
+			/* Early retirement is enabled and we're past the date... */
+			e->player_avail = 0;
+			AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
+		}
+	}
+
 	if (age < e->duration_phase_1) {
 		uint start = e->reliability_start;
 		e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start;
@@ -471,6 +482,7 @@
 
 		er->to = INVALID_ENGINE;
 		er->next = NULL;
+		er->group_id = DEFAULT_GROUP;
 		return er;
 	}
 
@@ -483,12 +495,12 @@
 /**
  * Retrieves the EngineRenew that specifies the replacement of the given
  * engine type from the given renewlist */
-static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine)
+static EngineRenew *GetEngineReplacement(EngineRenewList erl, EngineID engine, GroupID group)
 {
 	EngineRenew *er = (EngineRenew *)erl;
 
 	while (er) {
-		if (er->from == engine) return er;
+		if (er->from == engine && er->group_id == group) return er;
 		er = er->next;
 	}
 	return NULL;
@@ -507,18 +519,18 @@
 	*erl = NULL; // Empty list
 }
 
-EngineID EngineReplacement(EngineRenewList erl, EngineID engine)
+EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group)
 {
-	const EngineRenew *er = GetEngineReplacement(erl, engine);
+	const EngineRenew *er = GetEngineReplacement(erl, engine, group);
 	return er == NULL ? INVALID_ENGINE : er->to;
 }
 
-int32 AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, uint32 flags)
+int32 AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, uint32 flags)
 {
 	EngineRenew *er;
 
 	/* Check if the old vehicle is already in the list */
-	er = GetEngineReplacement(*erl, old_engine);
+	er = GetEngineReplacement(*erl, old_engine, group);
 	if (er != NULL) {
 		if (flags & DC_EXEC) er->to = new_engine;
 		return 0;
@@ -530,6 +542,7 @@
 	if (flags & DC_EXEC) {
 		er->from = old_engine;
 		er->to = new_engine;
+		er->group_id = group;
 
 		/* Insert before the first element */
 		er->next = (EngineRenew *)(*erl);
@@ -539,14 +552,14 @@
 	return 0;
 }
 
-int32 RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, uint32 flags)
+int32 RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, uint32 flags)
 {
 	EngineRenew *er = (EngineRenew *)(*erl);
 	EngineRenew *prev = NULL;
 
 	while (er)
 	{
-		if (er->from == engine) {
+		if (er->from == engine && er->group_id == group) {
 			if (flags & DC_EXEC) {
 				if (prev == NULL) { // First element
 					/* The second becomes the new first element */
@@ -567,11 +580,11 @@
 }
 
 static const SaveLoad _engine_renew_desc[] = {
-	SLE_VAR(EngineRenew, from, SLE_UINT16),
-	SLE_VAR(EngineRenew, to,   SLE_UINT16),
+	    SLE_VAR(EngineRenew, from,     SLE_UINT16),
+	    SLE_VAR(EngineRenew, to,       SLE_UINT16),
 
-	SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS),
-
+	    SLE_REF(EngineRenew, next,     REF_ENGINE_RENEWS),
+	SLE_CONDVAR(EngineRenew, group_id, SLE_UINT16, 60, SL_MAX_VERSION),
 	SLE_END()
 };
 
@@ -597,6 +610,9 @@
 
 		er = GetEngineRenew(index);
 		SlObject(er, _engine_renew_desc);
+
+		/* Advanced vehicle lists got added */
+		if (CheckSavegameVersion(60)) er->group_id = DEFAULT_GROUP;
 	}
 }
 
--- a/src/engine.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/engine.h	Fri May 25 00:25:08 2007 +0000
@@ -105,6 +105,7 @@
 	byte refit_cost;
 	byte misc_flags;
 	byte callbackmask;
+	byte retire_early; ///< Number of years early to retire vehicle
 };
 
 struct Engine {
@@ -119,7 +120,7 @@
 	PlayerByte preview_player;
 	byte preview_wait;
 	byte player_avail;
-	byte type; ///< type, ie VEH_ROAD, VEH_TRAIN, etc. Same as in vehicle.h
+	VehicleType type; ///< type, ie VEH_ROAD, VEH_TRAIN, etc. Same as in vehicle.h
 };
 
 /**
@@ -271,6 +272,7 @@
 	EngineID from;
 	EngineID to;
 	EngineRenew *next;
+	GroupID group_id;
 };
 
 /**
@@ -316,7 +318,7 @@
  * @return The engine type to replace with, or INVALID_ENGINE if no
  * replacement is in the list.
  */
-EngineID EngineReplacement(EngineRenewList erl, EngineID engine);
+EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group);
 
 /**
  * Add an engine replacement to the given renewlist.
@@ -326,7 +328,7 @@
  * @param flags The calling command flags.
  * @return 0 on success, CMD_ERROR on failure.
  */
-int32 AddEngineReplacement(EngineRenewList* erl, EngineID old_engine, EngineID new_engine, uint32 flags);
+int32 AddEngineReplacement(EngineRenewList* erl, EngineID old_engine, EngineID new_engine, GroupID group, uint32 flags);
 
 /**
  * Remove an engine replacement from a given renewlist.
@@ -335,12 +337,12 @@
  * @param flags The calling command flags.
  * @return 0 on success, CMD_ERROR on failure.
  */
-int32 RemoveEngineReplacement(EngineRenewList* erl, EngineID engine, uint32 flags);
+int32 RemoveEngineReplacement(EngineRenewList* erl, EngineID engine, GroupID group, uint32 flags);
 
 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
  * @param type The type of engine
  */
-void AddRemoveEngineFromAutoreplaceAndBuildWindows(byte type);
+void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type);
 
 /* Engine list manipulators - current implementation is only C wrapper of CBlobT<EngineID> class (helpers.cpp) */
 void EngList_Create(EngineList *el);            ///< Creates engine list
--- a/src/functions.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/functions.h	Fri May 25 00:25:08 2007 +0000
@@ -30,7 +30,6 @@
 /* standard */
 void ShowInfo(const char *str);
 void CDECL ShowInfoF(const char *str, ...);
-void NORETURN CDECL error(const char *str, ...);
 
 /* openttd.cpp */
 
--- a/src/gfx.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/gfx.cpp	Fri May 25 00:25:08 2007 +0000
@@ -18,6 +18,7 @@
 #include "fontcache.h"
 #include "genworld.h"
 #include "debug.h"
+#include "zoom.hpp"
 
 #ifdef _DEBUG
 bool _dbg_screen_rect;
@@ -64,12 +65,12 @@
 
 void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch)
 {
-	byte *dstp = (byte*)dst;
-	byte *srcp = (byte*)src;
+	Pixel *dstp = (Pixel *)dst;
+	Pixel *srcp = (Pixel *)src;
 
 	assert(h >= 0);
 	for (; h != 0; --h) {
-		memcpy(dstp, srcp, w);
+		memcpy(dstp, srcp, w * sizeof(Pixel));
 		dstp += dstpitch;
 		srcp += srcpitch;
 	}
@@ -110,7 +111,7 @@
 		}
 
 		for (ht = height; ht > 0; --ht) {
-			memcpy(dst, src, width);
+			memcpy(dst, src, width * sizeof(Pixel));
 			src -= p;
 			dst -= p;
 		}
@@ -136,7 +137,7 @@
 		/* the y-displacement may be 0 therefore we have to use memmove,
 		 * because source and destination may overlap */
 		for (ht = height; ht > 0; --ht) {
-			memmove(dst, src, width);
+			memmove(dst, src, width * sizeof(Pixel));
 			src += p;
 			dst += p;
 		}
@@ -153,7 +154,7 @@
 	const int otop = top;
 	const int oleft = left;
 
-	if (dpi->zoom != 0) return;
+	if (dpi->zoom != ZOOM_LVL_NORMAL) return;
 	if (left > right || top > bottom) return;
 	if (right < dpi->left || left >= dpi->left + dpi->width) return;
 	if (bottom < dpi->top || top >= dpi->top + dpi->height) return;
@@ -175,7 +176,7 @@
 	if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
 		if (!HASBIT(color, USE_COLORTABLE)) {
 			do {
-				memset(dst, color, right);
+				memset(dst, color, right * sizeof(Pixel));
 				dst += dpi->pitch;
 			} while (--bottom);
 		} else {
@@ -737,142 +738,7 @@
 	int pitch;
 };
 
-static void GfxBlitTileZoomIn(BlitterParams *bp)
-{
-	const byte *src_o = bp->sprite;
-	const byte *src;
-	int num, skip;
-	byte done;
-	Pixel *dst;
-	const byte *ctab;
-
-	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-
-					for (; num >= 4; num -=4) {
-						dst[3] = ctab[src[3]];
-						dst[2] = ctab[src[2]];
-						dst[1] = ctab[src[1]];
-						dst[0] = ctab[src[0]];
-						dst += 4;
-						src += 4;
-					}
-					for (; num != 0; num--) *dst++ = ctab[*src++];
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-
-		case BM_TRANSPARENT:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					for (; num != 0; num--) {
-						*dst = ctab[*dst];
-						dst++;
-					}
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-
-		default:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-#if defined(_WIN32)
-					if (num & 1) *dst++ = *src++;
-					if (num & 2) { *(uint16*)dst = *(uint16*)src; dst += 2; src += 2; }
-					if (num >>= 2) {
-						do {
-							*(uint32*)dst = *(uint32*)src;
-							dst += 4;
-							src += 4;
-						} while (--num != 0);
-					}
-#else
-					memcpy(dst, src, num);
-#endif
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-			} while (--bp->height != 0);
-			break;
-	}
-}
-
-static void GfxBlitZoomInUncomp(BlitterParams *bp)
+static void GfxBlitZoomUncomp(BlitterParams *bp, ZoomLevel zoom)
 {
 	const byte *src = bp->sprite;
 	Pixel *dst = bp->dst;
@@ -883,62 +749,48 @@
 	assert(height > 0);
 	assert(width > 0);
 
+	height = UnScaleByZoom(height, zoom);
+
 	switch (bp->mode) {
 		case BM_COLOUR_REMAP: {
 			const byte *ctab = _color_remap_ptr;
 
-			do {
-				for (i = 0; i != width; i++) {
-					byte b = ctab[src[i]];
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++) {
+					byte b = ctab[src[ScaleByZoom(i, zoom)]];
 
 					if (b != 0) dst[i] = b;
 				}
-				src += bp->width_org;
+				src += ScaleByZoom(bp->width_org, zoom);
 				dst += bp->pitch;
-			} while (--height != 0);
+			}
 			break;
 		}
 
 		case BM_TRANSPARENT: {
 			const byte *ctab = _color_remap_ptr;
 
-			do {
-				for (i = 0; i != width; i++)
-					if (src[i] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org;
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
+					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = ctab[dst[i]];
+				src += ScaleByZoom(bp->width_org, zoom);
 				dst += bp->pitch;
-			} while (--height != 0);
+			}
 			break;
 		}
 
 		default:
-			do {
-				int n = width;
-
-				for (; n >= 4; n -= 4) {
-					if (src[0] != 0) dst[0] = src[0];
-					if (src[1] != 0) dst[1] = src[1];
-					if (src[2] != 0) dst[2] = src[2];
-					if (src[3] != 0) dst[3] = src[3];
-
-					dst += 4;
-					src += 4;
-				}
-
-				for (; n != 0; n--) {
-					if (src[0] != 0) dst[0] = src[0];
-					src++;
-					dst++;
-				}
-
-				src += bp->width_org - width;
-				dst += bp->pitch - width;
-			} while (--height != 0);
+			for (; height != 0; height--) {
+				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
+					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = src[ScaleByZoom(i, zoom)];
+				src += ScaleByZoom(bp->width_org, zoom);
+				dst += bp->pitch;
+			}
 			break;
 	}
 }
 
-static void GfxBlitTileZoomMedium(BlitterParams *bp)
+static void GfxBlitTileZoom(BlitterParams *bp, ZoomLevel zoom)
 {
 	const byte *src_o = bp->sprite;
 	const byte *src;
@@ -948,484 +800,111 @@
 	const byte *ctab;
 
 	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
 
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
+	for (;;) {
+		do {
+			done = src_o[0];
+			num = done & 0x7F;
+			skip = src_o[1];
+			src = src_o + 2;
+			src_o += num + 2;
 
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
+			dst = bp->dst;
 
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
+			if (zoom >= ZOOM_LVL_OUT_2X && (skip & 1)) {
+				skip += 1;
+				src += 1;
+				num -= 1;
+				if (num <= 0) continue;
+			}
 
+			if (zoom >= ZOOM_LVL_OUT_4X && (skip & 2)) {
+				skip += 2;
+				src += 2;
+				num -= 2;
+				if (num <= 0) continue;
+			}
+
+			if (zoom >= ZOOM_LVL_OUT_8X && (skip & 4)) {
+				skip += 4;
+				src += 4;
+				num -= 4;
+				if (num <= 0) continue;
+			}
+
+			if (zoom >= ZOOM_LVL_OUT_16X && (skip & 8)) {
+				skip += 8;
+				src += 8;
+				num -= 8;
+				if (num <= 0) continue;
+			}
+
+			if ( (skip -= bp->start_x) > 0) {
+				dst += UnScaleByZoom(skip, zoom);
+			} else {
+				src -= skip;
+				num += skip;
+				if (num <= 0) continue;
+				skip = 0;
+			}
+
+			skip = skip + num - bp->width;
+			if (skip > 0) {
+				num -= skip;
+				if (num <= 0) continue;
+			}
+
+			num = UnScaleByZoom(num + ScaleByZoom(1, zoom) - 1, zoom);
+
+			switch (bp->mode) {
+				case BM_COLOUR_REMAP:
 					ctab = _color_remap_ptr;
-					num = (num + 1) >> 1;
 					for (; num != 0; num--) {
 							*dst = ctab[*src];
 							dst++;
-							src += 2;
+							src += ScaleByZoom(1, zoom);
 					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-
-		case BM_TRANSPARENT:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
+					break;
 
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						if (--num == 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
+				case BM_TRANSPARENT:
 					ctab = _color_remap_ptr;
-					num = (num + 1) >> 1;
 					for (; num != 0; num--) {
 							*dst = ctab[*dst];
 							dst++;
 					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-
-		default:
-			do {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
+					break;
 
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 1;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					num = (num + 1) >> 1;
-
+				default:
 					for (; num != 0; num--) {
 							*dst = *src;
 							dst++;
-							src += 2;
+							src += ScaleByZoom(1, zoom);
 					}
-
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-			} while (--bp->height != 0);
-			break;
-	}
-}
-
-static void GfxBlitZoomMediumUncomp(BlitterParams *bp)
-{
-	const byte *src = bp->sprite;
-	Pixel *dst = bp->dst;
-	int height = bp->height;
-	int width = bp->width;
-	int i;
-
-	assert(height > 0);
-	assert(width > 0);
-
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP: {
-			const byte *ctab = _color_remap_ptr;
+					break;
+			}
 
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++) {
-					byte b = ctab[src[i * 2]];
-
-					if (b != 0) dst[i] = b;
-				}
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		case BM_TRANSPARENT: {
-			const byte *ctab = _color_remap_ptr;
 
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++)
-					if (src[i * 2] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
+		} while (!(done & 0x80));
+
+		bp->dst += bp->pitch;
+		if (--bp->height == 0) return;
+
+		for (int i = 0; i < ScaleByZoom(1, zoom) - 1; i++) {
+			do {
+				done = src_o[0];
+				src_o += (done & 0x7F) + 2;
+			} while (!(done & 0x80));
+			if (--bp->height == 0) return;
 		}
-
-		default:
-			for (height >>= 1; height != 0; height--) {
-				for (i = 0; i != width >> 1; i++)
-					if (src[i * 2] != 0) dst[i] = src[i * 2];
-				src += bp->width_org * 2;
-				dst += bp->pitch;
-			}
-			break;
 	}
 }
 
-static void GfxBlitTileZoomOut(BlitterParams *bp)
-{
-	const byte *src_o = bp->sprite;
-	const byte *src;
-	int num, skip;
-	byte done;
-	Pixel *dst;
-	const byte *ctab;
-
-	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						src += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					num = (num + 3) >> 2;
-					for (; num != 0; num--) {
-							*dst = ctab[*src];
-							dst++;
-							src += 4;
-					}
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-
-		case BM_TRANSPARENT:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					ctab = _color_remap_ptr;
-					num = (num + 3) >> 2;
-					for (; num != 0; num--) {
-							*dst = ctab[*dst];
-							dst++;
-					}
-
-				} while (!(done & 0x80));
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-
-		default:
-			for (;;) {
-				do {
-					done = src_o[0];
-					num = done & 0x7F;
-					skip = src_o[1];
-					src = src_o + 2;
-					src_o += num + 2;
-
-					dst = bp->dst;
-
-					if (skip & 1) {
-						skip++;
-						src++;
-						if (--num == 0) continue;
-					}
-
-					if (skip & 2) {
-						skip += 2;
-						src += 2;
-						num -= 2;
-						if (num <= 0) continue;
-					}
-
-					if ( (skip -= bp->start_x) > 0) {
-						dst += skip >> 2;
-					} else {
-						src -= skip;
-						num += skip;
-						if (num <= 0) continue;
-						skip = 0;
-					}
-
-					skip = skip + num - bp->width;
-					if (skip > 0) {
-						num -= skip;
-						if (num <= 0) continue;
-					}
-
-					num = (num + 3) >> 2;
-
-					for (; num != 0; num--) {
-							*dst = *src;
-							dst++;
-							src += 4;
-					}
-				} while (!(done & 0x80));
-
-				bp->dst += bp->pitch;
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-
-				do {
-					done = src_o[0];
-					src_o += (done & 0x7F) + 2;
-				} while (!(done & 0x80));
-				if (--bp->height == 0) return;
-			}
-			break;
-	}
-}
-
-static void GfxBlitZoomOutUncomp(BlitterParams *bp)
-{
-	const byte *src = bp->sprite;
-	Pixel *dst = bp->dst;
-	int height = bp->height;
-	int width = bp->width;
-	int i;
-
-	assert(height > 0);
-	assert(width > 0);
-
-	switch (bp->mode) {
-		case BM_COLOUR_REMAP: {
-			const byte *ctab = _color_remap_ptr;
-
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++) {
-					byte b = ctab[src[i * 4]];
-
-					if (b != 0) dst[i] = b;
-				}
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		case BM_TRANSPARENT: {
-			const byte *ctab = _color_remap_ptr;
-
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++)
-					if (src[i * 4] != 0) dst[i] = ctab[dst[i]];
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-		}
-
-		default:
-			for (height >>= 2; height != 0; height--) {
-				for (i = 0; i != width >> 2; i++)
-					if (src[i * 4] != 0) dst[i] = src[i * 4];
-				src += bp->width_org * 4;
-				dst += bp->pitch;
-			}
-			break;
-	}
-}
-
-
 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
 {
 	const DrawPixelInfo *dpi = _cur_dpi;
 	int start_x, start_y;
 	BlitterParams bp;
-	int zoom_mask = ~((1 << dpi->zoom) - 1);
+	int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1);
 
 	/* decode sprite header */
 	x += sprite->x_offs;
@@ -1444,7 +923,7 @@
 		/* tile blit */
 		start_y = 0;
 
-		if (dpi->zoom > 0) {
+		if (dpi->zoom > ZOOM_LVL_NORMAL) {
 			start_y += bp.height & ~zoom_mask;
 			bp.height &= zoom_mask;
 			if (bp.height == 0) return;
@@ -1457,7 +936,7 @@
 			start_y -= y;
 			y = 0;
 		} else {
-			bp.dst += bp.pitch * (y >> dpi->zoom);
+			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
 		}
 		bp.start_y = start_y;
 
@@ -1475,19 +954,14 @@
 			x = 0;
 		}
 		bp.start_x = start_x;
-		bp.dst += x >> dpi->zoom;
+		bp.dst += UnScaleByZoom(x, dpi->zoom);
 
 		if ( (x = x + bp.width - dpi->width) > 0) {
 			bp.width -= x;
 			if (bp.width <= 0) return;
 		}
 
-		switch (dpi->zoom) {
-			default: NOT_REACHED();
-			case 0: GfxBlitTileZoomIn(&bp);     break;
-			case 1: GfxBlitTileZoomMedium(&bp); break;
-			case 2: GfxBlitTileZoomOut(&bp);    break;
-		}
+		GfxBlitTileZoom(&bp, dpi->zoom);
 	} else {
 		bp.sprite += bp.width * (bp.height & ~zoom_mask);
 		bp.height &= zoom_mask;
@@ -1501,7 +975,7 @@
 			bp.sprite -= bp.width * y;
 			y = 0;
 		} else {
-			bp.dst += bp.pitch * (y >> dpi->zoom);
+			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
 		}
 
 		if (bp.height > dpi->height - y) {
@@ -1517,19 +991,14 @@
 			bp.sprite -= x;
 			x = 0;
 		}
-		bp.dst += x >> dpi->zoom;
+		bp.dst += UnScaleByZoom(x, dpi->zoom);
 
 		if (bp.width > dpi->width - x) {
 			bp.width = dpi->width - x;
 			if (bp.width <= 0) return;
 		}
 
-		switch (dpi->zoom) {
-			default: NOT_REACHED();
-			case 0: GfxBlitZoomInUncomp(&bp);     break;
-			case 1: GfxBlitZoomMediumUncomp(&bp); break;
-			case 2: GfxBlitZoomOutUncomp(&bp);    break;
-		}
+		GfxBlitZoomUncomp(&bp, dpi->zoom);
 	}
 }
 
@@ -1946,7 +1415,7 @@
 {
 	const DrawPixelInfo *o = _cur_dpi;
 
-	n->zoom = 0;
+	n->zoom = ZOOM_LVL_NORMAL;
 
 	assert(width > 0);
 	assert(height > 0);
--- a/src/gfx.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/gfx.h	Fri May 25 00:25:08 2007 +0000
@@ -6,6 +6,7 @@
 #define GFX_H
 
 #include "openttd.h"
+#include "zoom.hpp"
 
 enum WindowKeyCodes {
 	WKC_SHIFT = 0x8000,
@@ -136,7 +137,7 @@
 	Pixel *dst_ptr;
 	int left, top, width, height;
 	int pitch;
-	uint16 zoom;
+	ZoomLevel zoom;
 };
 
 struct Colour {
--- a/src/gfxinit.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/gfxinit.cpp	Fri May 25 00:25:08 2007 +0000
@@ -393,6 +393,9 @@
 	assert(load_index == SPR_ROADSTOP_BASE);
 	load_index += LoadGrfFile("roadstops.grf", load_index, i++);
 
+	assert(load_index == SPR_GROUP_BASE);
+	load_index += LoadGrfFile("group.grf", load_index, i++);
+
 	/* Initialize the unicode to sprite mapping table */
 	InitializeUnicodeGlyphMap();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/group.h	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,97 @@
+/* $Id$ */
+
+/** @file group.h */
+
+#ifndef GROUP_H
+#define GROUP_H
+
+#include "oldpool.h"
+
+enum {
+	DEFAULT_GROUP = 0xFFFE,
+	INVALID_GROUP = 0xFFFF,
+};
+
+struct Group {
+	StringID string_id;                     ///< Group Name
+
+	uint16 num_vehicle;                     ///< Number of vehicles wich belong to the group
+	PlayerID owner;                         ///< Group Owner
+	GroupID index;                          ///< Array index
+	VehicleTypeByte vehicle_type;           ///< Vehicle type of the group
+
+	bool replace_protection;                ///< If set to true, the global autoreplace have no effect on the group
+	uint16 num_engines[TOTAL_NUM_ENGINES];  ///< Caches the number of engines of each type the player owns (no need to save this)
+};
+
+DECLARE_OLD_POOL(Group, Group, 5, 2047)
+
+
+static inline bool IsValidGroup(const Group *g)
+{
+	return g->string_id != STR_NULL;
+}
+
+static inline void DestroyGroup(Group *g)
+{
+	DeleteName(g->string_id);
+}
+
+static inline void DeleteGroup(Group *g)
+{
+	DestroyGroup(g);
+	g->string_id = STR_NULL;
+}
+
+static inline bool IsValidGroupID(GroupID index)
+{
+	return index < GetGroupPoolSize() && IsValidGroup(GetGroup(index));
+}
+
+static inline bool IsDefaultGroupID(GroupID index)
+{
+	return (index == DEFAULT_GROUP);
+}
+
+static inline StringID GetGroupName(GroupID index)
+{
+	if (!IsValidGroupID(index)) return STR_NULL;
+
+	return GetGroup(index)->string_id;
+}
+
+
+#define FOR_ALL_GROUPS_FROM(g, start) for (g = GetGroup(start); g != NULL; g = (g->index + 1U < GetGroupPoolSize()) ? GetGroup(g->index + 1) : NULL) if (IsValidGroup(g))
+#define FOR_ALL_GROUPS(g) FOR_ALL_GROUPS_FROM(g, 0)
+
+/**
+ * Get the current size of the GroupPool
+ */
+static inline uint GetGroupArraySize(void)
+{
+	const Group *g;
+	uint num = 0;
+
+	FOR_ALL_GROUPS(g) num++;
+
+	return num;
+}
+
+static inline void IncreaseGroupNumVehicle(GroupID id_g)
+{
+	if (IsValidGroupID(id_g)) GetGroup(id_g)->num_vehicle++;
+}
+
+static inline void DecreaseGroupNumVehicle(GroupID id_g)
+{
+	if (IsValidGroupID(id_g)) GetGroup(id_g)->num_vehicle--;
+}
+
+
+void InitializeGroup();
+void SetTrainGroupID(Vehicle *v, GroupID grp);
+void UpdateTrainGroupID(Vehicle *v);
+void RemoveVehicleFromGroup(const Vehicle *v);
+void RemoveAllGroupsForPlayer(const Player *p);
+
+#endif /* GROUP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/group_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,450 @@
+/* $Id$ */
+
+/** @file group_cmd.cpp Handling of the engine groups */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "functions.h"
+#include "player.h"
+#include "table/strings.h"
+#include "command.h"
+#include "vehicle.h"
+#include "saveload.h"
+#include "debug.h"
+#include "group.h"
+#include "train.h"
+#include "aircraft.h"
+#include "string.h"
+#include "window.h"
+#include "vehicle_gui.h"
+
+/**
+ * Update the num engines of a groupID. Decrease the old one and increase the new one
+ * @note called in SetTrainGroupID and UpdateTrainGroupID
+ * @param i     EngineID we have to update
+ * @param old_g index of the old group
+ * @param new_g index of the new group
+ */
+static inline void UpdateNumEngineGroup(EngineID i, GroupID old_g, GroupID new_g)
+{
+	if (old_g != new_g) {
+		/* Decrease the num engines of EngineID i of the old group if it's not the default one */
+		if (!IsDefaultGroupID(old_g) && IsValidGroupID(old_g)) GetGroup(old_g)->num_engines[i]--;
+
+		/* Increase the num engines of EngineID i of the new group if it's not the new one */
+		if (!IsDefaultGroupID(new_g) && IsValidGroupID(new_g)) GetGroup(new_g)->num_engines[i]++;
+	}
+}
+
+
+/**
+ * Called if a new block is added to the group-pool
+ */
+static void GroupPoolNewBlock(uint start_item)
+{
+	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
+	 * TODO - This is just a temporary stage, this will be removed. */
+	for (Group *g = GetGroup(start_item); g != NULL; g = (g->index + 1U < GetGroupPoolSize()) ? GetGroup(g->index + 1) : NULL) g->index = start_item++;
+}
+
+DEFINE_OLD_POOL(Group, Group, GroupPoolNewBlock, NULL)
+
+static Group *AllocateGroup(void)
+{
+	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
+	 * TODO - This is just a temporary stage, this will be removed. */
+	for (Group *g = GetGroup(0); g != NULL; g = (g->index + 1U < GetGroupPoolSize()) ? GetGroup(g->index + 1) : NULL) {
+		if (!IsValidGroup(g)) {
+			const GroupID index = g->index;
+
+			memset(g, 0, sizeof(*g));
+			g->index = index;
+
+			return g;
+		}
+	}
+
+	/* Check if we can add a block to the pool */
+	return (AddBlockToPool(&_Group_pool)) ? AllocateGroup() : NULL;
+}
+
+void InitializeGroup(void)
+{
+	CleanPool(&_Group_pool);
+	AddBlockToPool(&_Group_pool);
+}
+
+
+static WindowClass GetWCForVT(VehicleType vt)
+{
+	switch (vt) {
+		default:
+		case VEH_TRAIN:    return WC_TRAINS_LIST;
+		case VEH_ROAD:     return WC_ROADVEH_LIST;
+		case VEH_SHIP:     return WC_SHIPS_LIST;
+		case VEH_AIRCRAFT: return WC_AIRCRAFT_LIST;
+	}
+}
+
+
+/**
+ * Add a vehicle to a group
+ * @param tile unused
+ * @param p1   vehicle type
+ * @param p2   unused
+ */
+int32 CmdCreateGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	VehicleType vt = (VehicleType)p1;
+	if (!IsPlayerBuildableVehicleType(vt)) return CMD_ERROR;
+
+	Group *g = AllocateGroup();
+	if (g == NULL) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		g->owner = _current_player;
+		g->string_id = STR_SV_GROUP_NAME;
+		g->replace_protection = false;
+		g->vehicle_type = vt;
+
+		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+
+/**
+ * Add a vehicle to a group
+ * @param tile unused
+ * @param p1   index of array group
+ *      - p1 bit 0-15 : GroupID
+ * @param p2   unused
+ */
+int32 CmdDeleteGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	if (!IsValidGroupID(p1)) return CMD_ERROR;
+
+	Group *g = GetGroup(p1);
+	if (g->owner != _current_player) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		Vehicle *v;
+
+		/* Add all vehicles belong to the group to the default group */
+		FOR_ALL_VEHICLES(v) {
+			if (v->group_id == g->index && v->type == g->vehicle_type) v->group_id = DEFAULT_GROUP;
+		}
+
+		/* If we set an autoreplace for the group we delete, remove it. */
+		if (_current_player < MAX_PLAYERS) {
+			Player *p;
+			EngineRenew *er;
+
+			p = GetPlayer(_current_player);
+			FOR_ALL_ENGINE_RENEWS(er) {
+				if (er->group_id == g->index) RemoveEngineReplacementForPlayer(p, er->from, g->index, flags);
+			}
+		}
+
+		VehicleType vt = g->vehicle_type;
+
+		/* Delete the Replace Vehicle Windows */
+		DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
+		DeleteGroup(g);
+
+		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+
+/**
+ * Rename a group
+ * @param tile unused
+ * @param p1   index of array group
+ *   - p1 bit 0-15 : GroupID
+ * @param p2   unused
+ */
+int32 CmdRenameGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	if (!IsValidGroupID(p1) || StrEmpty(_cmd_text)) return CMD_ERROR;
+
+	Group *g = GetGroup(p1);
+	if (g->owner != _current_player) return CMD_ERROR;
+
+	/* Create the name */
+	StringID str = AllocateName(_cmd_text, 0);
+	if (str == STR_NULL) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		/* Delete the old name */
+		DeleteName(g->string_id);
+		/* Assign the new one */
+		g->string_id = str;
+
+		InvalidateWindowData(GetWCForVT(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+
+/**
+ * Add a vehicle to a group
+ * @param tile unused
+ * @param p1   index of array group
+ *   - p1 bit 0-15 : GroupID
+ * @param p2   vehicle to add to a group
+ *   - p2 bit 0-15 : VehicleID
+ */
+int32 CmdAddVehicleGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	GroupID new_g = p1;
+
+	if (!IsValidVehicleID(p2) || (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g))) return CMD_ERROR;
+
+	if (IsValidGroupID(new_g)) {
+		Group *g = GetGroup(new_g);
+		if (g->owner != _current_player) return CMD_ERROR;
+	}
+
+	Vehicle *v = GetVehicle(p2);
+	if (v->owner != _current_player || (v->type == VEH_TRAIN && !IsFrontEngine(v))) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		DecreaseGroupNumVehicle(v->group_id);
+		IncreaseGroupNumVehicle(new_g);
+
+		switch (v->type) {
+			default: NOT_REACHED();
+			case VEH_TRAIN:
+				SetTrainGroupID(v, new_g);
+				break;
+			case VEH_ROAD:
+			case VEH_SHIP:
+			case VEH_AIRCRAFT:
+				if (IsEngineCountable(v)) UpdateNumEngineGroup(v->engine_type, v->group_id, new_g);
+				v->group_id = new_g;
+				break;
+		}
+
+		/* Update the Replace Vehicle Windows */
+		InvalidateWindow(WC_REPLACE_VEHICLE, v->type);
+		InvalidateWindowData(GetWCForVT(v->type), (v->type << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+/**
+ * Add all shared vehicles of all vehicles from a group
+ * @param tile unused
+ * @param p1   index of group array
+ *  - p1 bit 0-15 : GroupID
+ * @param p2   type of vehicles
+ */
+int32 CmdAddSharedVehicleGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	VehicleType type = (VehicleType)p2;
+	if (!IsValidGroupID(p1) || !IsPlayerBuildableVehicleType(type)) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		Vehicle *v;
+		VehicleType type = (VehicleType)p2;
+		GroupID id_g = p1;
+		uint subtype = (type == VEH_AIRCRAFT) ? AIR_AIRCRAFT : 0;
+
+		/* Find the first front engine which belong to the group id_g
+		 * then add all shared vehicles of this front engine to the group id_g */
+		FOR_ALL_VEHICLES(v) {
+			if ((v->type == type) && (
+					(type == VEH_TRAIN && IsFrontEngine(v)) ||
+					(type != VEH_TRAIN && v->subtype <= subtype))) {
+				if (v->group_id != id_g) continue;
+
+				/* For each shared vehicles add it to the group */
+				for (Vehicle *v2 = GetFirstVehicleFromSharedList(v); v2 != NULL; v2 = v2->next_shared) {
+					if (v2->group_id != id_g) CmdAddVehicleGroup(tile, flags, id_g, v2->index);
+				}
+			}
+		}
+
+		InvalidateWindowData(GetWCForVT(type), (type << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+
+/**
+ * Remove all vehicles from a group
+ * @param tile unused
+ * @param p1   index of group array
+ * - p1 bit 0-15 : GroupID
+ * @param p2   type of vehicles
+ */
+int32 CmdRemoveAllVehiclesGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	VehicleType type = (VehicleType)p2;
+	if (!IsValidGroupID(p1) || !IsPlayerBuildableVehicleType(type)) return CMD_ERROR;
+
+	Group *g = GetGroup(p1);
+	if (g->owner != _current_player) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		GroupID old_g = p1;
+		uint subtype = (type == VEH_AIRCRAFT) ? AIR_AIRCRAFT : 0;
+		Vehicle *v;
+
+		/* Find each Vehicle that belongs to the group old_g and add it to the default group */
+		FOR_ALL_VEHICLES(v) {
+			if ((v->type == type) && (
+					(type == VEH_TRAIN && IsFrontEngine(v)) ||
+					(type != VEH_TRAIN && v->subtype <= subtype))) {
+				if (v->group_id != old_g) continue;
+
+				/* Add The Vehicle to the default group */
+				CmdAddVehicleGroup(tile, flags, DEFAULT_GROUP, v->index);
+			}
+		}
+
+		InvalidateWindowData(GetWCForVT(type), (type << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+
+/**
+ * (Un)set global replace protection from a group
+ * @param tile unused
+ * @param p1   index of group array
+ * - p1 bit 0-15 : GroupID
+ * @param p2
+ * - p2 bit 0    : 1 to set or 0 to clear protection.
+ */
+int32 CmdSetGroupReplaceProtection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+	if (!IsValidGroupID(p1)) return CMD_ERROR;
+
+	Group *g = GetGroup(p1);
+	if (g->owner != _current_player) return CMD_ERROR;
+
+	if (flags & DC_EXEC) {
+		g->replace_protection = HASBIT(p2, 0);
+
+		InvalidateWindowData(GetWCForVT(g->vehicle_type), (g->vehicle_type << 11) | VLW_GROUP_LIST | _current_player);
+	}
+
+	return 0;
+}
+
+/**
+ * Decrease the num_vehicle variable before delete an front engine from a group
+ * @note Called in CmdSellRailWagon and DeleteLasWagon,
+ * @param v     FrontEngine of the train we want to remove.
+ */
+void RemoveVehicleFromGroup(const Vehicle *v)
+{
+	if (!IsValidVehicle(v) || v->type != VEH_TRAIN || !IsFrontEngine(v)) return;
+
+	if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
+}
+
+
+/**
+ * Affect the groupID of a train to new_g.
+ * @note called in CmdAddVehicleGroup and CmdMoveRailVehicle
+ * @param v     First vehicle of the chain.
+ * @param new_g index of array group
+ */
+void SetTrainGroupID(Vehicle *v, GroupID new_g)
+{
+	if (!IsValidGroupID(new_g) && !IsDefaultGroupID(new_g)) return;
+
+	assert(IsValidVehicle(v) && v->type == VEH_TRAIN && IsFrontEngine(v));
+
+	for (Vehicle *u = v; u != NULL; u = u->next) {
+		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
+
+		u->group_id = new_g;
+	}
+
+	/* Update the Replace Vehicle Windows */
+	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
+}
+
+
+/**
+ * Recalculates the groupID of a train. Should be called each time a vehicle is added
+ * to/removed from the chain,.
+ * @note this needs to be called too for 'wagon chains' (in the depot, without an engine)
+ * @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon
+ * @param v First vehicle of the chain.
+ */
+void UpdateTrainGroupID(Vehicle *v)
+{
+	assert(IsValidVehicle(v) && v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)));
+
+	GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP;
+	for (Vehicle *u = v; u != NULL; u = u->next) {
+		if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
+
+		u->group_id = new_g;
+	}
+
+	/* Update the Replace Vehicle Windows */
+	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
+}
+
+
+void RemoveAllGroupsForPlayer(const Player *p)
+{
+	Group *g;
+
+	FOR_ALL_GROUPS(g) {
+		if (p->index == g->owner) DeleteGroup(g);
+	}
+}
+
+
+static const SaveLoad _group_desc[] = {
+  SLE_VAR(Group, string_id,          SLE_UINT16),
+  SLE_VAR(Group, num_vehicle,        SLE_UINT16),
+  SLE_VAR(Group, owner,              SLE_UINT8),
+  SLE_VAR(Group, vehicle_type,       SLE_UINT8),
+  SLE_VAR(Group, replace_protection, SLE_BOOL),
+  SLE_END()
+};
+
+
+static void Save_GROUP(void)
+{
+	Group *g;
+
+	FOR_ALL_GROUPS(g) {
+		SlSetArrayIndex(g->index);
+		SlObject(g, _group_desc);
+	}
+}
+
+
+static void Load_GROUP(void)
+{
+	int index;
+
+	while ((index = SlIterateArray()) != -1) {
+		if (!AddBlockIfNeeded(&_Group_pool, index)) {
+			error("Groups: failed loading savegame: too many groups");
+		}
+
+		Group *g = GetGroup(index);
+		SlObject(g, _group_desc);
+	}
+}
+
+extern const ChunkHandler _group_chunk_handlers[] = {
+	{ 'GRPS', Save_GROUP, Load_GROUP, CH_ARRAY | CH_LAST},
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/group_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,801 @@
+/* $Id$ */
+
+/** @file group_gui.cpp */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "functions.h"
+#include "table/strings.h"
+#include "table/sprites.h"
+#include "window.h"
+#include "gui.h"
+#include "gfx.h"
+#include "vehicle.h"
+#include "command.h"
+#include "engine.h"
+#include "vehicle_gui.h"
+#include "depot.h"
+#include "train.h"
+#include "date.h"
+#include "group.h"
+#include "helpers.hpp"
+#include "viewport.h"
+#include "strings.h"
+#include "debug.h"
+
+
+struct Sorting {
+	Listing aircraft;
+	Listing roadveh;
+	Listing ship;
+	Listing train;
+};
+
+static Sorting _sorting;
+
+
+static void BuildGroupList(grouplist_d* gl, PlayerID owner, VehicleType vehicle_type)
+{
+	const Group** list;
+	const Group *g;
+	uint n = 0;
+
+	if (!(gl->l.flags & VL_REBUILD)) return;
+
+	list = MallocT<const Group*>(GetGroupArraySize());
+	if (list == NULL) {
+		error("Could not allocate memory for the group-sorting-list");
+	}
+
+	FOR_ALL_GROUPS(g) {
+		if (g->owner == owner && g->vehicle_type == vehicle_type) list[n++] = g;
+	}
+
+	free((void*)gl->sort_list);
+	gl->sort_list = MallocT<const Group *>(n);
+	if (n != 0 && gl->sort_list == NULL) {
+		error("Could not allocate memory for the group-sorting-list");
+	}
+	gl->l.list_length = n;
+
+	for (uint i = 0; i < n; ++i) gl->sort_list[i] = list[i];
+	free((void*)list);
+
+	gl->l.flags &= ~VL_REBUILD;
+	gl->l.flags |= VL_RESORT;
+}
+
+
+static int CDECL GroupNameSorter(const void *a, const void *b)
+{
+	static const Group *last_group[2] = { NULL, NULL };
+	static char         last_name[2][64] = { "", "" };
+
+	const Group *ga = *(const Group**)a;
+	const Group *gb = *(const Group**)b;
+	int r;
+
+	if (ga != last_group[0]) {
+		last_group[0] = ga;
+		SetDParam(0, ga->index);
+		GetString(last_name[0], ga->string_id, lastof(last_name[0]));
+	}
+
+	if (gb != last_group[1]) {
+		last_group[1] = gb;
+		SetDParam(0, gb->index);
+		GetString(last_name[1], gb->string_id, lastof(last_name[1]));
+	}
+
+	r = strcmp(last_name[0], last_name[1]); // sort by name
+
+	if (r == 0) return ga->index - gb->index;
+
+	return r;
+}
+
+
+static void SortGroupList(grouplist_d *gl)
+{
+	if (!(gl->l.flags & VL_RESORT)) return;
+
+	qsort((void*)gl->sort_list, gl->l.list_length, sizeof(gl->sort_list[0]), GroupNameSorter);
+
+	gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+	gl->l.flags &= ~VL_RESORT;
+}
+
+
+enum GroupListWidgets {
+	GRP_WIDGET_CLOSEBOX = 0,
+	GRP_WIDGET_CAPTION,
+	GRP_WIDGET_STICKY,
+	GRP_WIDGET_EMPTY_TOP_LEFT,
+	GRP_WIDGET_ALL_VEHICLES,
+	GRP_WIDGET_LIST_GROUP,
+	GRP_WIDGET_LIST_GROUP_SCROLLBAR,
+	GRP_WIDGET_SORT_BY_ORDER,
+	GRP_WIDGET_SORT_BY_TEXT,
+	GRP_WIDGET_SORT_BY_DROPDOWN,
+	GRP_WIDGET_EMPTY_TOP_RIGHT,
+	GRP_WIDGET_LIST_VEHICLE,
+	GRP_WIDGET_LIST_VEHICLE_SCROLLBAR,
+	GRP_WIDGET_CREATE_GROUP,
+	GRP_WIDGET_DELETE_GROUP,
+	GRP_WIDGET_RENAME_GROUP,
+	GRP_WIDGET_EMPTY1,
+	GRP_WIDGET_REPLACE_PROTECTION,
+	GRP_WIDGET_EMPTY2,
+	GRP_WIDGET_AVAILABLE_VEHICLES,
+	GRP_WIDGET_MANAGE_VEHICLES,
+	GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
+	GRP_WIDGET_STOP_ALL,
+	GRP_WIDGET_START_ALL,
+	GRP_WIDGET_EMPTY_BOTTOM_RIGHT,
+	GRP_WIDGET_RESIZE,
+};
+
+
+static const Widget _group_widgets[] = {
+{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,             STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,  RESIZE_RIGHT,    14,    11,   513,     0,    13, 0x0,                  STR_018C_WINDOW_TITLE_DRAG_THIS},
+{  WWT_STICKYBOX,     RESIZE_LR,    14,   514,   525,     0,    13, 0x0,                  STR_STICKY_BUTTON},
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   200,    14,    25, 0x0,                  STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   200,    26,    39, 0x0,                  STR_NULL},
+{     WWT_MATRIX, RESIZE_BOTTOM,    14,     0,   188,    39,   220, 0x701,                STR_GROUPS_CLICK_ON_GROUP_FOR_TIP},
+{  WWT_SCROLLBAR, RESIZE_BOTTOM,    14,   189,   200,    26,   220, 0x0,                  STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   201,   281,    14,    25, STR_SORT_BY,          STR_SORT_ORDER_TIP},
+{      WWT_PANEL,   RESIZE_NONE,    14,   282,   435,    14,    25, 0x0,                  STR_SORT_CRITERIA_TIP},
+{    WWT_TEXTBTN,   RESIZE_NONE,    14,   436,   447,    14,    25, STR_0225,             STR_SORT_CRITERIA_TIP},
+{      WWT_PANEL,  RESIZE_RIGHT,    14,   448,   525,    14,    25, 0x0,                  STR_NULL},
+{     WWT_MATRIX,     RESIZE_RB,    14,   201,   513,    26,   233, 0x701,                STR_NULL},
+{ WWT_SCROLL2BAR,    RESIZE_LRB,    14,   514,   525,    26,   233, 0x0,                  STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,     0,    23,   221,   245, 0x0,                  STR_GROUP_CREATE_TIP},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,    24,    47,   221,   245, 0x0,                  STR_GROUP_DELETE_TIP},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,    48,    71,   221,   245, 0x0,                  STR_GROUP_RENAME_TIP},
+{      WWT_PANEL,     RESIZE_TB,    14,    72,   164,   221,   245, 0x0,                  STR_NULL},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,   165,   188,   221,   245, 0x0,                  STR_GROUP_REPLACE_PROTECTION_TIP},
+{      WWT_PANEL,     RESIZE_TB,    14,   189,   200,   221,   245, 0x0,                  STR_NULL},
+{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   201,   306,   234,   245, 0x0,                  STR_AVAILABLE_ENGINES_TIP},
+{    WWT_TEXTBTN,     RESIZE_TB,    14,   307,   411,   234,   245, STR_MANAGE_LIST,      STR_MANAGE_LIST_TIP},
+{    WWT_TEXTBTN,     RESIZE_TB,    14,   412,   423,   234,   245, STR_0225,             STR_MANAGE_LIST_TIP},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,   424,   435,   234,   245, SPR_FLAG_VEH_STOPPED, STR_MASS_STOP_LIST_TIP},
+{ WWT_PUSHIMGBTN,     RESIZE_TB,    14,   436,   447,   234,   245, SPR_FLAG_VEH_RUNNING, STR_MASS_START_LIST_TIP},
+{      WWT_PANEL,    RESIZE_RTB,    14,   448,   513,   234,   245, 0x0,                  STR_NULL},
+{  WWT_RESIZEBOX,   RESIZE_LRTB,    14,   514,   525,   234,   245, 0x0,                  STR_RESIZE_BUTTON},
+{   WIDGETS_END},
+};
+
+
+static void CreateVehicleGroupWindow(Window *w)
+{
+	const PlayerID owner = (PlayerID)GB(w->window_number, 0, 8);
+	groupveh_d *gv = &WP(w, groupveh_d);
+	grouplist_d *gl = &WP(w, groupveh_d).gl;
+
+	w->caption_color = owner;
+	w->hscroll.cap = 10 * 29;
+	w->resize.step_width = 1;
+
+	switch (gv->vehicle_type) {
+		default: NOT_REACHED();
+		case VEH_TRAIN:
+		case VEH_ROAD:
+			w->vscroll.cap = 14;
+			w->vscroll2.cap = 8;
+			w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_SMALL;
+			break;
+		case VEH_SHIP:
+		case VEH_AIRCRAFT:
+			w->vscroll.cap = 10;
+			w->vscroll2.cap = 4;
+			w->resize.step_height = PLY_WND_PRC__SIZE_OF_ROW_BIG2;
+			break;
+	}
+
+	w->widget[GRP_WIDGET_LIST_GROUP].data = (w->vscroll.cap << 8) + 1;
+	w->widget[GRP_WIDGET_LIST_VEHICLE].data = (w->vscroll2.cap << 8) + 1;
+
+	switch (gv->vehicle_type) {
+		default: NOT_REACHED(); break;
+		case VEH_TRAIN:    gv->_sorting = &_sorting.train;    break;
+		case VEH_ROAD:     gv->_sorting = &_sorting.roadveh;  break;
+		case VEH_SHIP:     gv->_sorting = &_sorting.ship;     break;
+		case VEH_AIRCRAFT: gv->_sorting = &_sorting.aircraft; break;
+	}
+
+	gv->sort_list = NULL;
+	gv->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
+	gv->l.sort_type = gv->_sorting->criteria;
+	gv->l.flags = VL_REBUILD | (gv->_sorting->order ? VL_DESC : VL_NONE);
+	gv->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;	// Set up resort timer
+
+	gl->sort_list = NULL;
+	gl->l.flags = VL_REBUILD | VL_NONE;
+	gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;	// Set up resort timer
+
+	gv->group_sel = DEFAULT_GROUP;
+
+	switch (gv->vehicle_type) {
+		case VEH_TRAIN:
+			w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_883D_TRAINS_CLICK_ON_TRAIN_FOR;
+			w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_TRAINS;
+
+			w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_TRAIN;
+			w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_TRAIN;
+			w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_TRAIN;
+			break;
+
+		case VEH_ROAD:
+			w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_901A_ROAD_VEHICLES_CLICK_ON;
+			w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_ROAD_VEHICLES;
+
+			w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_ROADVEH;
+			w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_ROADVEH;
+			w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_ROADVEH;
+			break;
+
+		case VEH_SHIP:
+			w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_9823_SHIPS_CLICK_ON_SHIP_FOR;
+			w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_SHIPS;
+
+			w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_SHIP;
+			w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_SHIP;
+			w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_SHIP;
+			break;
+
+		case VEH_AIRCRAFT:
+			w->widget[GRP_WIDGET_LIST_VEHICLE].tooltips = STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT;
+			w->widget[GRP_WIDGET_AVAILABLE_VEHICLES].data = STR_AVAILABLE_AIRCRAFT;
+
+			w->widget[GRP_WIDGET_CREATE_GROUP].data = SPR_GROUP_CREATE_AIRCRAFT;
+			w->widget[GRP_WIDGET_RENAME_GROUP].data = SPR_GROUP_RENAME_AIRCRAFT;
+			w->widget[GRP_WIDGET_DELETE_GROUP].data = SPR_GROUP_DELETE_AIRCRAFT;
+			break;
+
+		default: NOT_REACHED();
+	}
+}
+
+/**
+ * Update/redraw the group action dropdown
+ * @param w   the window the dropdown belongs to
+ * @param gid the currently selected group in the window
+ */
+static void UpdateGroupActionDropdown(Window *w, GroupID gid, bool refresh = true)
+{
+	if (refresh && !IsWindowWidgetLowered(w, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) return;
+
+	static StringID action_str[] = {
+		STR_REPLACE_VEHICLES,
+		STR_SEND_FOR_SERVICING,
+		STR_SEND_TRAIN_TO_DEPOT,
+		STR_NULL,
+		STR_NULL,
+		INVALID_STRING_ID
+	};
+
+	action_str[3] = IsDefaultGroupID(gid) ? INVALID_STRING_ID : STR_GROUP_ADD_SHARED_VEHICLE;
+	action_str[4] = IsDefaultGroupID(gid) ? INVALID_STRING_ID : STR_GROUP_REMOVE_ALL_VEHICLES;
+
+	ShowDropDownMenu(w, action_str, 0, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN, 0, 0);
+}
+
+/**
+ * bitmask for w->window_number
+ * 0-7   PlayerID (owner)
+ * 11-15 vehicle type
+ **/
+static void GroupWndProc(Window *w, WindowEvent *e)
+{
+	const PlayerID owner = (PlayerID)GB(w->window_number, 0, 8);
+	const Player *p = GetPlayer(owner);
+	groupveh_d *gv = &WP(w, groupveh_d);
+	grouplist_d *gl = &WP(w, groupveh_d).gl;
+
+	gv->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
+
+	switch(e->event) {
+		case WE_INVALIDATE_DATA:
+			gv->l.flags |= VL_REBUILD;
+			gl->l.flags |= VL_REBUILD;
+			UpdateGroupActionDropdown(w, gv->group_sel);
+			SetWindowDirty(w);
+			break;
+
+		case WE_CREATE:
+			CreateVehicleGroupWindow(w);
+			break;
+
+		case WE_PAINT: {
+			int x = 203;
+			int y2 = PLY_WND_PRC__OFFSET_TOP_WIDGET;
+			int y1 = PLY_WND_PRC__OFFSET_TOP_WIDGET + 2;
+			int max;
+			int i;
+
+			/* If we select the default group, gv->list will contain all vehicles of the player
+			 * else gv->list will contain all vehicles which belong to the selected group */
+			BuildVehicleList(gv, owner, gv->group_sel, IsDefaultGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST);
+			SortVehicleList(gv);
+
+
+			BuildGroupList(gl, owner, gv->vehicle_type);
+			SortGroupList(gl);
+
+			SetVScrollCount(w, gl->l.list_length);
+			SetVScroll2Count(w, gv->l.list_length);
+
+			/* Disable all lists management button when the list is empty */
+			SetWindowWidgetsDisabledState(w, gv->l.list_length == 0,
+					GRP_WIDGET_STOP_ALL,
+					GRP_WIDGET_START_ALL,
+					GRP_WIDGET_MANAGE_VEHICLES,
+					GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN,
+					WIDGET_LIST_END);
+
+			/* Disable the group specific function when we select the default group */
+			SetWindowWidgetsDisabledState(w, IsDefaultGroupID(gv->group_sel),
+					GRP_WIDGET_DELETE_GROUP,
+					GRP_WIDGET_RENAME_GROUP,
+					GRP_WIDGET_REPLACE_PROTECTION,
+					WIDGET_LIST_END);
+
+			/* If selected_group == DEFAULT_GROUP, draw the standard caption
+			   We list all vehicles */
+			if (IsDefaultGroupID(gv->group_sel)) {
+				SetDParam(0, p->name_1);
+				SetDParam(1, p->name_2);
+				SetDParam(2, gv->l.list_length);
+
+				switch (gv->vehicle_type) {
+					case VEH_TRAIN:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_881B_TRAINS;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_TRAIN;
+						break;
+					case VEH_ROAD:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_9001_ROAD_VEHICLES;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_ROADVEH;
+						break;
+					case VEH_SHIP:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_9805_SHIPS;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_SHIP;
+						break;
+					case VEH_AIRCRAFT:
+						w->widget[GRP_WIDGET_CAPTION].data =  STR_A009_AIRCRAFT;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = SPR_GROUP_REPLACE_OFF_AIRCRAFT;
+						break;
+					default: NOT_REACHED(); break;
+				}
+			} else {
+				const Group *g = GetGroup(gv->group_sel);
+
+				SetDParam(0, g->index);
+				SetDParam(1, g->num_vehicle);
+
+				switch (gv->vehicle_type) {
+					case VEH_TRAIN:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_TRAINS_CAPTION;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_TRAIN : SPR_GROUP_REPLACE_OFF_TRAIN;
+						break;
+					case VEH_ROAD:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_ROADVEH_CAPTION;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_ROADVEH : SPR_GROUP_REPLACE_OFF_ROADVEH;
+						break;
+					case VEH_SHIP:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_SHIPS_CAPTION;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_SHIP : SPR_GROUP_REPLACE_OFF_SHIP;
+						break;
+					case VEH_AIRCRAFT:
+						w->widget[GRP_WIDGET_CAPTION].data = STR_GROUP_AIRCRAFTS_CAPTION;
+						w->widget[GRP_WIDGET_REPLACE_PROTECTION].data = (g->replace_protection) ? SPR_GROUP_REPLACE_ON_AIRCRAFT : SPR_GROUP_REPLACE_OFF_AIRCRAFT;
+						break;
+					default: NOT_REACHED(); break;
+				}
+			}
+
+
+			DrawWindowWidgets(w);
+
+			/* Draw Matrix Group
+			 * The selected group is drawn in white */
+			StringID str;
+
+			switch (gv->vehicle_type) {
+				case VEH_TRAIN:    str = STR_GROUP_ALL_TRAINS;    break;
+				case VEH_ROAD:     str = STR_GROUP_ALL_ROADS;     break;
+				case VEH_SHIP:     str = STR_GROUP_ALL_SHIPS;     break;
+				case VEH_AIRCRAFT: str = STR_GROUP_ALL_AIRCRAFTS; break;
+				default: NOT_REACHED(); break;
+			}
+			DrawString(10, y1, str, IsDefaultGroupID(gv->group_sel) ? 12 : 16);
+
+			max = min(w->vscroll.pos + w->vscroll.cap, gl->l.list_length);
+			for (i = w->vscroll.pos ; i < max ; ++i) {
+				const Group *g = gl->sort_list[i];
+
+				assert(g->owner == owner);
+
+				y1 += PLY_WND_PRC__SIZE_OF_ROW_TINY;
+
+				/* draw the selected group in white, else we draw it in black */
+				SetDParam(0, g->index);
+				DrawString(10, y1, STR_SV_GROUP_NAME, (gv->group_sel == g->index) ? 12 : 16);
+
+				/* draw the number of vehicles of the group */
+				SetDParam(0, g->num_vehicle);
+				DrawStringRightAligned(187, y1 + 1, STR_GROUP_TINY_NUM, (gv->group_sel == g->index) ? 12 : 16);
+			}
+
+			/* Draw Matrix Vehicle according to the vehicle list built before */
+			DrawString(285, 15, _vehicle_sort_listing[gv->l.sort_type], 0x10);
+			DoDrawString(gv->l.flags & VL_DESC ? DOWNARROW : UPARROW, 269, 15, 0x10);
+
+			max = min(w->vscroll2.pos + w->vscroll2.cap, gv->l.list_length);
+			for (i = w->vscroll2.pos ; i < max ; ++i) {
+				const Vehicle* v = gv->sort_list[i];
+				StringID str;
+
+				assert(v->type == gv->vehicle_type && v->owner == owner);
+
+				DrawVehicleImage(v, x + 19, y2 + 6, w->hscroll.cap, 0, gv->vehicle_sel);
+				DrawVehicleProfitButton(v, x, y2 + 13);
+
+				if (IsVehicleInDepot(v)) {
+					str = STR_021F;
+				} else {
+					str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2;
+				}
+				SetDParam(0, v->unitnumber);
+				DrawString(x, y2 + 2, str, 0);
+
+				if (w->resize.step_height == PLY_WND_PRC__SIZE_OF_ROW_BIG2) DrawSmallOrderList(v, x + 138, y2);
+
+				if (v->profit_this_year < 0) {
+					str = v->profit_last_year < 0 ?
+							STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR :
+							STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR;
+				} else {
+					str = v->profit_last_year < 0 ?
+							STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR :
+							STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR;
+				}
+
+				SetDParam(0, v->profit_this_year);
+				SetDParam(1, v->profit_last_year);
+				DrawString(x + 19, y2 + w->resize.step_height - 8, str, 0);
+
+				if (IsValidGroupID(v->group_id)) {
+					SetDParam(0, v->group_id);
+					DrawString(x + 19, y2, STR_GROUP_TINY_NAME, 16);
+				}
+
+				y2 += w->resize.step_height;
+			}
+
+			break;
+		}
+
+		case WE_CLICK:
+			switch(e->we.click.widget) {
+				case GRP_WIDGET_SORT_BY_ORDER: // Flip sorting method ascending/descending
+					gv->l.flags ^= VL_DESC;
+					gv->l.flags |= VL_RESORT;
+
+					gv->_sorting->order = !!(gv->l.flags & VL_DESC);
+					SetWindowDirty(w);
+					break;
+
+				case GRP_WIDGET_SORT_BY_TEXT:
+				case GRP_WIDGET_SORT_BY_DROPDOWN: // Select sorting criteria dropdown menu
+					ShowDropDownMenu(w, _vehicle_sort_listing, gv->l.sort_type,  GRP_WIDGET_SORT_BY_DROPDOWN, 0, 0);
+					return;
+
+				case GRP_WIDGET_ALL_VEHICLES: // All vehicles button
+					if (!IsDefaultGroupID(gv->group_sel)) {
+						gv->group_sel = DEFAULT_GROUP;
+						gv->l.flags |= VL_REBUILD;
+						UpdateGroupActionDropdown(w, gv->group_sel);
+						SetWindowDirty(w);
+					}
+					break;
+
+				case GRP_WIDGET_LIST_GROUP: { // Matrix Group
+					uint16 id_g = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 13) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+
+					if (id_g >= w->vscroll.cap) return;
+
+					id_g += w->vscroll.pos;
+
+					if (id_g >= gl->l.list_length) return;
+
+					gv->group_sel = gl->sort_list[id_g]->index;;
+
+					gv->l.flags |= VL_REBUILD;
+					UpdateGroupActionDropdown(w, gv->group_sel);
+					SetWindowDirty(w);
+					break;
+				}
+
+				case GRP_WIDGET_LIST_VEHICLE: { // Matrix Vehicle
+					uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)w->resize.step_height;
+					const Vehicle *v;
+
+					if (id_v >= w->vscroll2.cap) return; // click out of bounds
+
+					id_v += w->vscroll2.pos;
+
+					if (id_v >= gv->l.list_length) return; // click out of list bound
+
+					v = gv->sort_list[id_v];
+
+					gv->vehicle_sel = v->index;
+
+					if (IsValidVehicle(v)) {
+						CursorID image;
+
+						switch (gv->vehicle_type) {
+							case VEH_TRAIN:    image = GetTrainImage(v, DIR_W);    break;
+							case VEH_ROAD:     image = GetRoadVehImage(v, DIR_W);  break;
+							case VEH_SHIP:     image = GetShipImage(v, DIR_W);     break;
+							case VEH_AIRCRAFT: image = GetAircraftImage(v, DIR_W); break;
+							default: NOT_REACHED(); break;
+						}
+
+						SetObjectToPlaceWnd(image, GetVehiclePalette(v), 4, w);
+					}
+
+					SetWindowDirty(w);
+					break;
+				}
+
+				case GRP_WIDGET_CREATE_GROUP: // Create a new group
+					DoCommandP(0, gv->vehicle_type, 0, NULL, CMD_CREATE_GROUP | CMD_MSG(STR_GROUP_CAN_T_CREATE));
+					break;
+
+				case GRP_WIDGET_DELETE_GROUP: { // Delete the selected group
+					GroupID group = gv->group_sel;
+					gv->group_sel = DEFAULT_GROUP;
+
+					DoCommandP(0, group, 0, NULL, CMD_DELETE_GROUP | CMD_MSG(STR_GROUP_CAN_T_DELETE));
+					break;
+				}
+
+				case GRP_WIDGET_RENAME_GROUP: { // Rename the selected roup
+					assert(!IsDefaultGroupID(gv->group_sel));
+
+					const Group *g = GetGroup(gv->group_sel);
+
+					SetDParam(0, g->index);
+					ShowQueryString(g->string_id, STR_GROUP_RENAME_CAPTION, 31, 150, w, CS_ALPHANUMERAL);
+				}	break;
+
+
+				case GRP_WIDGET_AVAILABLE_VEHICLES:
+					ShowBuildVehicleWindow(0, gv->vehicle_type);
+					break;
+
+				case GRP_WIDGET_MANAGE_VEHICLES:
+				case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:  {
+					UpdateGroupActionDropdown(w, gv->group_sel, false);
+					break;
+				}
+
+
+				case GRP_WIDGET_START_ALL:
+				case GRP_WIDGET_STOP_ALL: { // Start/stop all vehicles of the list
+					DoCommandP(0, gv->group_sel, ((IsDefaultGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+														| (1 << 6)
+														| (e->we.click.widget == GRP_WIDGET_START_ALL ? (1 << 5) : 0)
+														| gv->vehicle_type, NULL, CMD_MASS_START_STOP);
+
+					break;
+				}
+
+				case GRP_WIDGET_REPLACE_PROTECTION:
+					if (!IsDefaultGroupID(gv->group_sel)) {
+						const Group *g = GetGroup(gv->group_sel);
+
+						DoCommandP(0, gv->group_sel, !g->replace_protection, NULL, CMD_SET_GROUP_REPLACE_PROTECTION);
+					}
+					break;
+			}
+
+			break;
+
+		case WE_DRAGDROP: {
+			switch (e->we.click.widget) {
+				case GRP_WIDGET_ALL_VEHICLES: // All trains
+					DoCommandP(0, DEFAULT_GROUP, gv->vehicle_sel, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
+
+					gv->vehicle_sel = INVALID_VEHICLE;
+
+					SetWindowDirty(w);
+
+					break;
+
+				case GRP_WIDGET_LIST_GROUP: { // Maxtrix group
+					uint16 id_g = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET - 13) / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+					const VehicleID vindex = gv->vehicle_sel;
+
+					gv->vehicle_sel = INVALID_VEHICLE;
+
+					SetWindowDirty(w);
+
+					if (id_g >= w->vscroll.cap) return;
+
+					id_g += w->vscroll.pos;
+
+					if (id_g >= gl->l.list_length) return;
+
+					DoCommandP(0, gl->sort_list[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE));
+
+					break;
+				}
+
+				case GRP_WIDGET_LIST_VEHICLE: { // Maxtrix vehicle
+					uint32 id_v = (e->we.click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / (int)w->resize.step_height;
+					const Vehicle *v;
+					const VehicleID vindex = gv->vehicle_sel;
+
+					gv->vehicle_sel = INVALID_VEHICLE;
+
+					SetWindowDirty(w);
+
+					if (id_v >= w->vscroll2.cap) return; // click out of bounds
+
+					id_v += w->vscroll2.pos;
+
+					if (id_v >= gv->l.list_length) return; // click out of list bound
+
+					v = gv->sort_list[id_v];
+
+					if (vindex == v->index) {
+						switch (gv->vehicle_type) {
+							default: NOT_REACHED(); break;
+							case VEH_TRAIN:    ShowTrainViewWindow(v);    break;
+							case VEH_ROAD:     ShowRoadVehViewWindow(v);  break;
+							case VEH_SHIP:     ShowShipViewWindow(v);     break;
+							case VEH_AIRCRAFT: ShowAircraftViewWindow(v); break;
+						}
+					}
+
+					break;
+				}
+			}
+			break;
+		}
+
+		case WE_ON_EDIT_TEXT:
+			if (!StrEmpty(e->we.edittext.str)) {
+				_cmd_text = e->we.edittext.str;
+
+				DoCommandP(0, gv->group_sel, 0, NULL, CMD_RENAME_GROUP | CMD_MSG(STR_GROUP_CAN_T_RENAME));
+			}
+			break;
+
+		case WE_RESIZE:
+			w->hscroll.cap += e->we.sizing.diff.x;
+			w->vscroll.cap += e->we.sizing.diff.y / PLY_WND_PRC__SIZE_OF_ROW_TINY;
+			w->vscroll2.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
+
+			w->widget[GRP_WIDGET_LIST_GROUP].data = (w->vscroll.cap << 8) + 1;
+			w->widget[GRP_WIDGET_LIST_VEHICLE].data = (w->vscroll2.cap << 8) + 1;
+			break;
+
+
+		case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
+			switch (e->we.dropdown.button) {
+				case GRP_WIDGET_SORT_BY_DROPDOWN:
+					if (gv->l.sort_type != e->we.dropdown.index) {
+						gv->l.flags |= VL_RESORT;
+						gv->l.sort_type = e->we.dropdown.index;
+						gv->_sorting->criteria = gv->l.sort_type;
+					}
+					break;
+
+				case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN:
+					assert(gv->l.list_length != 0);
+
+					switch (e->we.dropdown.index) {
+						case 0: // Replace window
+							ShowReplaceGroupVehicleWindow(gv->group_sel, gv->vehicle_type);
+							break;
+						case 1: // Send for servicing
+							DoCommandP(0, gv->group_sel, ((IsDefaultGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+										| DEPOT_MASS_SEND
+										| DEPOT_SERVICE, NULL, GetCmdSendToDepot(gv->vehicle_type));
+							break;
+						case 2: // Send to Depots
+							DoCommandP(0, gv->group_sel, ((IsDefaultGroupID(gv->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST) & VLW_MASK)
+										| DEPOT_MASS_SEND, NULL, GetCmdSendToDepot(gv->vehicle_type));
+							break;
+						case 3: // Add shared Vehicles
+							assert(!IsDefaultGroupID(gv->group_sel));
+
+							DoCommandP(0, gv->group_sel, gv->vehicle_type, NULL, CMD_ADD_SHARED_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_SHARED_VEHICLE));
+							break;
+						case 4: // Remove all Vehicles from the selected group
+							assert(!IsDefaultGroupID(gv->group_sel));
+
+							DoCommandP(0, gv->group_sel, gv->vehicle_type, NULL, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
+							break;
+						default: NOT_REACHED();
+					}
+					break;
+
+				default: NOT_REACHED();
+			}
+
+			SetWindowDirty(w);
+			break;
+
+
+		case WE_DESTROY:
+			free((void*)gv->sort_list);
+			free((void*)gl->sort_list);
+			break;
+
+
+		case WE_TICK: // resort the lists every 20 seconds orso (10 days)
+			if (--gv->l.resort_timer == 0) {
+				gv->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+				gv->l.flags |= VL_RESORT;
+				SetWindowDirty(w);
+			}
+			if (--gl->l.resort_timer == 0) {
+				gl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
+				gl->l.flags |= VL_RESORT;
+				SetWindowDirty(w);
+			}
+			break;
+		}
+}
+
+
+static const WindowDesc _group_desc = {
+	WDP_AUTO, WDP_AUTO, 526, 246,
+	WC_TRAINS_LIST, WC_NONE,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
+	_group_widgets,
+	GroupWndProc
+};
+
+void ShowPlayerGroup(PlayerID player, VehicleType vehicle_type)
+{
+	WindowClass wc;
+
+	switch (vehicle_type) {
+		default: NOT_REACHED();
+		case VEH_TRAIN:    wc = WC_TRAINS_LIST;   break;
+		case VEH_ROAD:     wc = WC_ROADVEH_LIST;  break;
+		case VEH_SHIP:     wc = WC_SHIPS_LIST;    break;
+		case VEH_AIRCRAFT: wc = WC_AIRCRAFT_LIST; break;
+	}
+
+	WindowNumber num = (vehicle_type << 11) | VLW_GROUP_LIST | player;
+	DeleteWindowById(wc, num);
+	Window *w = AllocateWindowDescFront(&_group_desc, num);
+	if (w == NULL) return;
+
+	w->window_class = wc;
+
+	switch (vehicle_type) {
+		default: NOT_REACHED();
+		case VEH_ROAD:
+			ResizeWindow(w, -66,   0);
+			/* FALL THROUGH */
+		case VEH_TRAIN:
+			w->resize.height = w->height - (PLY_WND_PRC__SIZE_OF_ROW_SMALL * 4); // Minimum of 4 vehicles
+			break;
+
+		case VEH_SHIP:
+		case VEH_AIRCRAFT:
+			ResizeWindow(w, -66, -52);
+			w->resize.height = w->height;  // Minimum of 4 vehicles
+			break;
+	}
+
+	/* Set the minimum window size to the current window size */
+	w->resize.width = w->width;
+}
--- a/src/gui.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/gui.h	Fri May 25 00:25:08 2007 +0000
@@ -46,7 +46,7 @@
 void ShowOrdersWindow(const Vehicle *v);
 
 /* road_gui.cpp */
-void ShowBuildRoadToolbar();
+void ShowBuildRoadToolbar(RoadType roadtype);
 void ShowBuildRoadScenToolbar();
 void ShowRoadVehViewWindow(const Vehicle *v);
 
@@ -68,14 +68,29 @@
 void PlaceProc_LevelLand(TileIndex tile);
 bool GUIPlaceProcDragXY(const WindowEvent *e);
 
-enum { // max 32 - 4 = 28 types
-	GUI_PlaceProc_DemolishArea    = 0 << 4,
-	GUI_PlaceProc_LevelArea       = 1 << 4,
-	GUI_PlaceProc_DesertArea      = 2 << 4,
-	GUI_PlaceProc_WaterArea       = 3 << 4,
-	GUI_PlaceProc_ConvertRailArea = 4 << 4,
-	GUI_PlaceProc_RockyArea       = 5 << 4,
-	GUI_PlaceProc_RemoveFromStation = 6 << 4,
+/** Drag and drop selection process, or, what to do with an area of land when
+ * you've selected it. */
+enum {
+	DDSP_DEMOLISH_AREA,
+	DDSP_LEVEL_AREA,
+	DDSP_CREATE_DESERT,
+	DDSP_CREATE_ROCKS,
+	DDSP_CREATE_WATER,
+	DDSP_PLANT_TREES,
+	DDSP_BUILD_BRIDGE,
+
+	/* Rail specific actions */
+	DDSP_PLACE_RAIL_NE,
+	DDSP_PLACE_RAIL_NW,
+	DDSP_PLACE_AUTORAIL,
+	DDSP_BUILD_SIGNALS,
+	DDSP_BUILD_STATION,
+	DDSP_REMOVE_STATION,
+	DDSP_CONVERT_RAIL,
+
+	/* Road specific actions */
+	DDSP_PLACE_ROAD_NE,
+	DDSP_PLACE_ROAD_NW,
 };
 
 /* misc_gui.cpp */
@@ -139,4 +154,6 @@
 /* vehicle_gui.cpp */
 void InitializeGUI();
 
+void ShowPlayerGroup(PlayerID player, VehicleType veh);
+
 #endif /* GUI_H */
--- a/src/industry.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/industry.h	Fri May 25 00:25:08 2007 +0000
@@ -14,7 +14,8 @@
 enum {
 	INVALID_INDUSTRY = 0xFFFF,
 	NUM_INDUSTRYTYPES = 37,
-	INDUTILE_NOANIM = 0xFF,        ///< flag to mark industry tiles as having no animation
+	INDUTILE_NOANIM = 0xFF,                   ///< flag to mark industry tiles as having no animation
+	INVALID_INDUSTRYTYPE = NUM_INDUSTRYTYPES, ///< one above amount is considered invalid
 };
 
 enum IndustryLifeType {
@@ -67,10 +68,8 @@
 	byte width;
 	byte height;
 	const Town* town;               ///< Nearest town
-	CargoID produced_cargo[2];      ///< 2 production cargo slots
 	uint16 cargo_waiting[2];        ///< amount of cargo produced per cargo
 	byte production_rate[2];        ///< production rate for each cargo
-	CargoID accepts_cargo[3];       ///< 3 input cargo slots
 	byte prod_level;                ///< general production level
 	uint16 last_mo_production[2];   ///< stats of last month production per cargo
 	uint16 last_mo_transported[2];  ///< stats of last month transport per cargo
@@ -79,7 +78,7 @@
 	uint16 total_transported[2];    ///< total units transported per cargo
 	uint16 counter;                 ///< used for animation and/or production (if available cargo)
 
-	byte type;                      ///< type of industry. see IT_COAL_MINE and others
+	IndustryType type;              ///< type of industry. see IT_COAL_MINE and others
 	OwnerByte owner;                ///< owner of the industry.  Which SHOULD always be (imho) OWNER_NONE
 	byte random_color;              ///< randomized colour of the industry, for display purpose
 	Year last_prod_year;            ///< last year of production
@@ -93,6 +92,16 @@
 	IndustryGfx gfx;
 };
 
+/** Data related to the handling of grf files.  Common to both industry and industry tile */
+struct GRFFileProps {
+	uint8 subst_id;
+	uint16 local_id;                      ///< id defined by the grf file for this industry
+	struct SpriteGroup *spritegroup;      ///< pointer to the different sprites of the industry
+	const struct GRFFile *grffile;        ///< grf file that introduced this house
+	uint8 override;                       ///< id of the entity been replaced by
+	bool enabled;                         ///< entity still avaible (by default true).newgrf can disable it, though
+};
+
 /**
  * Defines the data structure for constructing industry.
  */
@@ -107,6 +116,7 @@
 	byte minimal_cargo;                   ///< minimum amount of cargo transported to the stations
 	                                      ///< If the waiting cargo is less than this number, no cargo is moved to it
 	CargoID accepts_cargo[3];             ///< 3 accepted cargos
+	uint16 input_cargo_multiplier[3][2];  ///< Input cargo multipliers (multiply amount of incoming cargo for the produced cargos)
 	IndustryLifeType life_type;           ///< This is also known as Industry production flag, in newgrf specs
 	byte climate_availability;            ///< Bitmask, giving landscape enums as bit position
 	IndustyBehaviour behaviour;           ///< How this industry will behave, and how others entities can use it
@@ -118,11 +128,11 @@
 	StringID production_down_text;        ///< Message appearing when the industry's production is decreasing
 	byte appear_ingame[NUM_LANDSCAPE];    ///< Probability of appearance in game
 	byte appear_creation[NUM_LANDSCAPE];  ///< Probability of appearance during map creation
-	/* Newgrf stuff coming in */
+	uint8 number_of_sounds;               ///< Number of sounds available in the sounds array
+	const uint8 *random_sounds;           ///< array of random sounds.
+	/* Newgrf data */
 	uint16 callback_flags;                ///< Flags telling which grf callback is set
-	byte subst_id;
-	uint32 grfid;
-	byte override;
+	struct GRFFileProps grf_prop;         ///< properties related the the grf file
 };
 
 /**
@@ -134,11 +144,17 @@
 	byte anim_production;                 ///< Animation frame to start when goods are produced
 	byte anim_next;                       ///< Next frame in an animation
 	bool anim_state;                      ///< When true, the tile has to be drawn using the animation
-                                         ///< state instead of the construction state
+	                                      ///< state instead of the construction state
+	/* Newgrf data */
+	uint8 callback_flags;                ///< Flags telling which grf callback is set
+	struct GRFFileProps grf_prop;
 };
 
+/* industry_cmd.cpp*/
 const IndustrySpec *GetIndustrySpec(IndustryType thistype);    ///< Array of industries default data
 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx);  ///< Array of industry tiles default data
+void ResetIndustries();
+void PlantRandomFarmField(const Industry *i);
 
 /* smallmap_gui.cpp */
 void BuildIndustriesLegend();
@@ -220,10 +236,6 @@
 VARDEF const Industry** _industry_sort;
 VARDEF bool _industry_sort_dirty;
 
-
-void DeleteIndustry(Industry *is);
-void PlantRandomFarmField(const Industry *i);
-
 enum {
 	IT_COAL_MINE           =   0,
 	IT_POWER_STATION       =   1,
--- a/src/industry_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/industry_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -55,26 +55,16 @@
  * Retrieve the type for this industry.  Although it is accessed by a tile,
  * it will return the general type of industry, and not the sprite index
  * as would do GetIndustryGfx.
- * The same information can be accessed by looking at Industry->type
  * @param tile that is queried
  * @pre IsTileType(tile, MP_INDUSTRY)
  * @return general type for this industry, as defined in industry.h
  **/
 IndustryType GetIndustryType(TileIndex tile)
 {
-	IndustryGfx this_type = GetIndustryGfx(tile);
-	IndustryType iloop;
-
 	assert(IsTileType(tile, MP_INDUSTRY));
 
-	for (iloop = IT_COAL_MINE; iloop < NUM_INDUSTRYTYPES; iloop += 1) {
-		if (IS_BYTE_INSIDE(this_type, industry_gfx_Solver[iloop].MinGfx,
-				industry_gfx_Solver[iloop].MaxGfx + 1)) {
-			return iloop;
-		}
-	}
-
-	return IT_INVALID;  //we have not found equivalent, whatever the reason
+	const Industry *ind = GetIndustryByTile(tile);
+	return IsValidIndustry(ind) ? ind->type : (IndustryType)IT_INVALID;
 }
 
 /**
@@ -355,7 +345,7 @@
 
 		i->last_mo_production[0] += cw;
 
-		am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[0], cw);
+		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw);
 		i->last_mo_transported[0] += am;
 		if (am != 0) {
 			uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
@@ -377,7 +367,7 @@
 
 		i->last_mo_production[1] += cw;
 
-		am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[1], cw);
+		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[1], cw);
 		i->last_mo_transported[1] += am;
 	}
 }
@@ -745,14 +735,14 @@
 	ShowIndustryViewWindow(GetIndustryIndex(tile));
 }
 
-static uint32 GetTileTrackStatus_Industry(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	return 0;
 }
 
 static void GetProducedCargo_Industry(TileIndex tile, CargoID *b)
 {
-	const Industry *i = GetIndustryByTile(tile);
+	const IndustrySpec *i = GetIndustrySpec(GetIndustryByTile(tile)->type);
 
 	b[0] = i->produced_cargo[0];
 	b[1] = i->produced_cargo[1];
@@ -915,57 +905,17 @@
 		i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo
 }
 
-static const byte _industry_sounds[37][2] = {
-	{0},
-	{0},
-	{1, SND_28_SAWMILL},
-	{0},
-	{0},
-	{0},
-	{1, SND_03_FACTORY_WHISTLE},
-	{1, SND_03_FACTORY_WHISTLE},
-	{0},
-	{3, SND_24_SHEEP},
-	{0},
-	{0},
-	{0},
-	{0},
-	{1, SND_28_SAWMILL},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{1, SND_03_FACTORY_WHISTLE},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{0},
-	{1, SND_33_PLASTIC_MINE},
-	{0},
-	{0},
-	{0},
-	{0},
-};
-
-
 static void ProduceIndustryGoods(Industry *i)
 {
 	uint32 r;
 	uint num;
+	const IndustrySpec *indsp = GetIndustrySpec(i->type);
 
 	/* play a sound? */
 	if ((i->counter & 0x3F) == 0) {
-		if (CHANCE16R(1, 14, r) && (num = _industry_sounds[i->type][0]) != 0) {
+		if (CHANCE16R(1, 14, r) && (num = indsp->number_of_sounds) != 0) {
 			SndPlayTileFx(
-				(SoundFx)(_industry_sounds[i->type][1] + (((r >> 16) * num) >> 16)),
+				(SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
 				i->xy);
 		}
 	}
@@ -974,7 +924,7 @@
 
 	/* produce some cargo */
 	if ((i->counter & 0xFF) == 0) {
-		IndustyBehaviour indbehav = GetIndustrySpec(i->type)->behaviour;
+		IndustyBehaviour indbehav = indsp->behaviour;
 		i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + i->production_rate[0]);
 		i->cargo_waiting[1] = min(0xffff, i->cargo_waiting[1] + i->production_rate[1]);
 
@@ -1333,7 +1283,7 @@
 		/* check if an industry that accepts the same goods is nearby */
 		if (DistanceMax(tile, i->xy) <= 14 &&
 				indspec->accepts_cargo[0] != CT_INVALID &&
-				indspec->accepts_cargo[0] == i->accepts_cargo[0] && (
+				indspec->accepts_cargo[0] == indspec->accepts_cargo[0] && (
 					_game_mode != GM_EDITOR ||
 					!_patches.same_industry_close ||
 					!_patches.multiple_industry_per_town
@@ -1384,11 +1334,6 @@
 	i->width = i->height = 0;
 	i->type = type;
 
-	i->produced_cargo[0] = indspec->produced_cargo[0];
-	i->produced_cargo[1] = indspec->produced_cargo[1];
-	i->accepts_cargo[0] = indspec->accepts_cargo[0];
-	i->accepts_cargo[1] = indspec->accepts_cargo[1];
-	i->accepts_cargo[2] = indspec->accepts_cargo[2];
 	i->production_rate[0] = indspec->production_rate[0];
 	i->production_rate[1] = indspec->production_rate[1];
 
@@ -1638,7 +1583,7 @@
 			break;
 
 		default: /* INDUSTRY_PRODUCTION */
-			for (j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){
+			for (j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){
 				uint32 r = Random();
 				int old_prod, new_prod, percent;
 				int mag;
@@ -1664,7 +1609,7 @@
 				mag = abs(percent);
 				if (mag >= 10) {
 					SetDParam(2, mag);
-					SetDParam(0, GetCargo(i->produced_cargo[j])->name);
+					SetDParam(0, GetCargo(indspec->produced_cargo[j])->name);
 					SetDParam(1, i->index);
 					AddNewsItem(
 						percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
@@ -1693,40 +1638,26 @@
 {
 	byte pct;
 	bool refresh = false;
+	const IndustrySpec *indsp = GetIndustrySpec(i->type);
 
-	if (i->produced_cargo[0] != CT_INVALID) {
-		pct = 0;
-		if (i->last_mo_production[0] != 0) {
-			i->last_prod_year = _cur_year;
-			pct = min(i->last_mo_transported[0] * 256 / i->last_mo_production[0], 255);
+	for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
+		if (indsp->produced_cargo[j] != CT_INVALID) {
+			pct = 0;
+			if (i->last_mo_production[j] != 0) {
+				i->last_prod_year = _cur_year;
+				pct = min(i->last_mo_transported[j] * 256 / i->last_mo_production[j], 255);
+			}
+			i->pct_transported[j] = pct;
+
+			i->total_production[j] = i->last_mo_production[j];
+			i->last_mo_production[j] = 0;
+
+			i->total_transported[j] = i->last_mo_transported[j];
+			i->last_mo_transported[j] = 0;
+			refresh = true;
 		}
-		i->pct_transported[0] = pct;
-
-		i->total_production[0] = i->last_mo_production[0];
-		i->last_mo_production[0] = 0;
-
-		i->total_transported[0] = i->last_mo_transported[0];
-		i->last_mo_transported[0] = 0;
-		refresh = true;
 	}
 
-	if (i->produced_cargo[1] != CT_INVALID) {
-		pct = 0;
-		if (i->last_mo_production[1] != 0) {
-			i->last_prod_year = _cur_year;
-			pct = min(i->last_mo_transported[1] * 256 / i->last_mo_production[1], 255);
-		}
-		i->pct_transported[1] = pct;
-
-		i->total_production[1] = i->last_mo_production[1];
-		i->last_mo_production[1] = 0;
-
-		i->total_transported[1] = i->last_mo_transported[1];
-		i->last_mo_transported[1] = 0;
-		refresh = true;
-	}
-
-
 	if (refresh)
 		InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
 
@@ -1920,10 +1851,10 @@
 	    SLE_VAR(Industry, width,               SLE_UINT8),
 	    SLE_VAR(Industry, height,              SLE_UINT8),
 	    SLE_REF(Industry, town,                REF_TOWN),
-	    SLE_ARR(Industry, produced_cargo,      SLE_UINT8,  2),
+	SLE_CONDNULL( 2, 2, 60),       ///< used to be industry's produced_cargo
 	    SLE_ARR(Industry, cargo_waiting,       SLE_UINT16, 2),
 	    SLE_ARR(Industry, production_rate,     SLE_UINT8,  2),
-	    SLE_ARR(Industry, accepts_cargo,       SLE_UINT8,  3),
+	SLE_CONDNULL( 3, 2, 60),       ///< used to be industry's accepts_cargo
 	    SLE_VAR(Industry, prod_level,          SLE_UINT8),
 	    SLE_ARR(Industry, last_mo_production,  SLE_UINT16, 2),
 	    SLE_ARR(Industry, last_mo_transported, SLE_UINT16, 2),
--- a/src/industry_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/industry_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -287,8 +287,9 @@
 
 static inline bool IsProductionAlterable(const Industry *i)
 {
+	const IndustrySpec *ind = GetIndustrySpec(i->type);
 	return ((_game_mode == GM_EDITOR || _cheats.setup_prod.value) &&
-		     (i->accepts_cargo[0] == CT_INVALID || i->accepts_cargo[0] == CT_VALUABLES));
+			(ind->accepts_cargo[0] == CT_INVALID || ind->accepts_cargo[0] == CT_VALUABLES));
 }
 
 static void IndustryViewWndProc(Window *w, WindowEvent *e)
@@ -300,30 +301,31 @@
 	switch (e->event) {
 	case WE_PAINT: {
 		const Industry *i = GetIndustry(w->window_number);
+		const IndustrySpec *ind = GetIndustrySpec(i->type);
 
 		SetDParam(0, w->window_number);
 		DrawWindowWidgets(w);
 
-		if (i->accepts_cargo[0] != CT_INVALID) {
+		if (ind->accepts_cargo[0] != CT_INVALID) {
 			StringID str;
 
-			SetDParam(0, GetCargo(i->accepts_cargo[0])->name);
+			SetDParam(0, GetCargo(ind->accepts_cargo[0])->name);
 			str = STR_4827_REQUIRES;
-			if (i->accepts_cargo[1] != CT_INVALID) {
-				SetDParam(1, GetCargo(i->accepts_cargo[1])->name);
+			if (ind->accepts_cargo[1] != CT_INVALID) {
+				SetDParam(1, GetCargo(ind->accepts_cargo[1])->name);
 				str = STR_4828_REQUIRES;
-				if (i->accepts_cargo[2] != CT_INVALID) {
-					SetDParam(2, GetCargo(i->accepts_cargo[2])->name);
+				if (ind->accepts_cargo[2] != CT_INVALID) {
+					SetDParam(2, GetCargo(ind->accepts_cargo[2])->name);
 					str = STR_4829_REQUIRES;
 				}
 			}
 			DrawString(2, 107, str, 0);
 		}
 
-		if (i->produced_cargo[0] != CT_INVALID) {
+		if (ind->produced_cargo[0] != CT_INVALID) {
 			DrawString(2, 117, STR_482A_PRODUCTION_LAST_MONTH, 0);
 
-			SetDParam(0, i->produced_cargo[0]);
+			SetDParam(0, ind->produced_cargo[0]);
 			SetDParam(1, i->total_production[0]);
 
 			SetDParam(2, i->pct_transported[0] * 100 >> 8);
@@ -334,8 +336,8 @@
 						!isProductionMinimum(i, 0), !isProductionMaximum(i, 0));
 			}
 
-			if (i->produced_cargo[1] != CT_INVALID) {
-				SetDParam(0, i->produced_cargo[1]);
+			if (ind->produced_cargo[1] != CT_INVALID) {
+				SetDParam(0, ind->produced_cargo[1]);
 				SetDParam(1, i->total_production[1]);
 				SetDParam(2, i->pct_transported[1] * 100 >> 8);
 				DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), 137, STR_482B_TRANSPORTED, 0);
@@ -365,7 +367,8 @@
 
 			x = e->we.click.pt.x;
 			line = (e->we.click.pt.y - 127) / 10;
-			if (e->we.click.pt.y >= 127 && IS_INT_INSIDE(line, 0, 2) && i->produced_cargo[line] != CT_INVALID) {
+			if (e->we.click.pt.y >= 127 && IS_INT_INSIDE(line, 0, 2) &&
+					GetIndustrySpec(i->type)->produced_cargo[line] != CT_INVALID) {
 				if (IS_INT_INSIDE(x, 5, 25) ) {
 					/* Clicked buttons, decrease or increase production */
 					if (x < 15) {
@@ -416,11 +419,13 @@
 
 static void UpdateIndustryProduction(Industry *i)
 {
-	if (i->produced_cargo[0] != CT_INVALID)
-		i->total_production[0] = 8 * i->production_rate[0];
+	const IndustrySpec *ind = GetIndustrySpec(i->type);
 
-	if (i->produced_cargo[1] != CT_INVALID)
-		i->total_production[1] = 8 * i->production_rate[1];
+	for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
+		if (ind->produced_cargo[j] != CT_INVALID) {
+			i->total_production[j] = 8 * i->production_rate[j];
+		}
+	}
 }
 
 static const Widget _industry_view_widgets[] = {
@@ -452,7 +457,7 @@
 		WP(w, vp2_d).data_1 = 0;
 		WP(w, vp2_d).data_2 = 0;
 		WP(w, vp2_d).data_3 = 0;
-		AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), 1);
+		AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
 	}
 }
 
@@ -482,6 +487,8 @@
 {
 	const Industry* i = *(const Industry**)a;
 	const Industry* j = *(const Industry**)b;
+	const IndustrySpec *ind_i = GetIndustrySpec(i->type);
+	const IndustrySpec *ind_j = GetIndustrySpec(j->type);
 	int r;
 
 	switch (_industry_sort_order >> 1) {
@@ -495,10 +502,10 @@
 			break;
 
 		case 2: /* Sort by Production */
-			if (i->produced_cargo[0] == CT_INVALID) {
-				r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1);
+			if (ind_i->produced_cargo[0] == CT_INVALID) {
+				r = (ind_j->produced_cargo[0] == CT_INVALID ? 0 : -1);
 			} else {
-				if (j->produced_cargo[0] == CT_INVALID) {
+				if (ind_j->produced_cargo[0] == CT_INVALID) {
 					r = 1;
 				} else {
 					r =
@@ -509,23 +516,23 @@
 			break;
 
 		case 3: /* Sort by transported fraction */
-			if (i->produced_cargo[0] == CT_INVALID) {
-				r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1);
+			if (ind_i->produced_cargo[0] == CT_INVALID) {
+				r = (ind_j->produced_cargo[0] == CT_INVALID ? 0 : -1);
 			} else {
-				if (j->produced_cargo[0] == CT_INVALID) {
+				if (ind_j->produced_cargo[0] == CT_INVALID) {
 					r = 1;
 				} else {
 					int pi;
 					int pj;
 
 					pi = i->pct_transported[0] * 100 >> 8;
-					if (i->produced_cargo[1] != CT_INVALID) {
+					if (ind_i->produced_cargo[1] != CT_INVALID) {
 						int p = i->pct_transported[1] * 100 >> 8;
 						if (p < pi) pi = p;
 					}
 
 					pj = j->pct_transported[0] * 100 >> 8;
-					if (j->produced_cargo[1] != CT_INVALID) {
+					if (ind_j->produced_cargo[1] != CT_INVALID) {
 						int p = j->pct_transported[1] * 100 >> 8;
 						if (p < pj) pj = p;
 					}
@@ -606,14 +613,15 @@
 
 		while (p < _num_industry_sort) {
 			const Industry* i = _industry_sort[p];
+			const IndustrySpec *ind = GetIndustrySpec(i->type);
 
 			SetDParam(0, i->index);
-			if (i->produced_cargo[0] != CT_INVALID) {
-				SetDParam(1, i->produced_cargo[0]);
+			if (ind->produced_cargo[0] != CT_INVALID) {
+				SetDParam(1, ind->produced_cargo[0]);
 				SetDParam(2, i->total_production[0]);
 
-				if (i->produced_cargo[1] != CT_INVALID) {
-					SetDParam(3, i->produced_cargo[1]);
+				if (ind->produced_cargo[1] != CT_INVALID) {
+					SetDParam(3, ind->produced_cargo[1]);
 					SetDParam(4, i->total_production[1]);
 					SetDParam(5, i->pct_transported[0] * 100 >> 8);
 					SetDParam(6, i->pct_transported[1] * 100 >> 8);
--- a/src/industry_map.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/industry_map.h	Fri May 25 00:25:08 2007 +0000
@@ -207,46 +207,6 @@
 	IndustryGfx MaxGfx; ///< The last gfx index for the industry type
 };
 
-/** Mapping of industry gfx to industry type */
-static const IndustryTypeSolver industry_gfx_Solver[IT_END] = {
-	{  0,   6}, ///< IT_COAL_MINE
-	{  7,  10}, ///< IT_POWER_STATION,
-	{ 11,  15}, ///< IT_SAWMILL,
-	{ 16,  17}, ///< IT_FOREST,
-	{ 18,  23}, ///< IT_OIL_REFINERY,
-	{ 24,  28}, ///< IT_OIL_RIG,
-	{ 29,  31}, ///< IT_OIL_WELL,
-	{ 32,  38}, ///< IT_FARM,
-	{ 39,  42}, ///< IT_FACTORY,
-	{ 43,  46}, ///< IT_PRINTING_WORKS,
-	{ 47,  51}, ///< IT_COPPER_MINE,
-	{ 52,  57}, ///< IT_STEEL_MILL,
-	{ 58,  59}, ///< IT_BANK_TEMP,
-	{ 60,  63}, ///< IT_FOOD_PROCESS,
-	{ 64,  71}, ///< IT_PAPER_MILL,
-	{ 72,  88}, ///< IT_GOLD_MINE,
-	{ 89,  90}, ///< IT_BANK_TROPIC_ARCTIC,
-	{ 91,  99}, ///< IT_DIAMOND_MINE,
-	{100, 115}, ///< IT_IRON_MINE,
-	{116, 116}, ///< IT_FRUIT_PLANTATION,
-	{117, 117}, ///< IT_RUBBER_PLANTATION,
-	{118, 119}, ///< IT_WATER_SUPPLY,
-	{120, 120}, ///< IT_WATER_TOWER,
-	{121, 124}, ///< IT_FACTORY_2,
-	{125, 128}, ///< IT_LUMBER_MILL,
-	{129, 130}, ///< IT_COTTON_CANDY,
-	{131, 134}, ///< IT_CANDY_FACTORY or sweet factory
-	{135, 136}, ///< IT_BATTERY_FARM,
-	{137, 137}, ///< IT_COLA_WELLS,
-	{138, 141}, ///< IT_TOY_SHOP,
-	{142, 147}, ///< IT_TOY_FACTORY,
-	{148, 155}, ///< IT_PLASTIC_FOUNTAINS,
-	{156, 159}, ///< IT_FIZZY_DRINK_FACTORY,
-	{160, 163}, ///< IT_BUBBLE_GENERATOR,
-	{164, 166}, ///< IT_TOFFEE_QUARRY,
-	{167, 174}  ///< IT_SUGAR_MINE,
-};
-
 /**
  * Get the animation loop number
  * @param tile the tile to get the animation loop number of
--- a/src/landscape.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/landscape.cpp	Fri May 25 00:25:08 2007 +0000
@@ -274,9 +274,9 @@
 	MarkTileDirtyByTile(tile);
 }
 
-uint32 GetTileTrackStatus(TileIndex tile, TransportType mode)
+uint32 GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode)
 {
-	return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode);
+	return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode);
 }
 
 void ChangeTileOwner(TileIndex tile, PlayerID old_player, PlayerID new_player)
--- a/src/landscape.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/landscape.h	Fri May 25 00:25:08 2007 +0000
@@ -44,7 +44,7 @@
 void DoClearSquare(TileIndex tile);
 void RunTileLoop();
 
-uint32 GetTileTrackStatus(TileIndex tile, TransportType mode);
+uint32 GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode);
 void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac);
 void ChangeTileOwner(TileIndex tile, PlayerID old_player, PlayerID new_player);
 void AnimateTile(TileIndex tile);
--- a/src/lang/american.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/american.txt	Fri May 25 00:25:08 2007 +0000
@@ -3,6 +3,8 @@
 ##isocode en_US
 ##plural 0
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Off edge of map
@@ -1046,6 +1048,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}New global pathfinding (NPF, overrides NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Always allow small airports: {ORANGE}{STRING}
 
@@ -1098,6 +1101,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Off
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Map scrollwheel speed: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automatically pause when starting a new game: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Use the advanced vehicle list: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Max trains per player: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Max road vehicles per player: {ORANGE}{STRING}
@@ -1585,6 +1589,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Railroad track with pre-signals
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Railroad track with exit-signals
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Railroad track with combo-signals
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Must remove railway station first
 
 
 
@@ -2012,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Heliport
 STR_SV_STNAME_FOREST                                            :{STRING} Forest
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3187,3 +3194,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Toggle transparency for buildables like stations, depots, waypoints and catenary
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Toggle transparency for bridges
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Toggle transparency for structures like lighthouses and antennas, maybe in future for eyecandy
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Group {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :All trains
+STR_GROUP_ALL_ROADS                                             :All road vehicles
+STR_GROUP_ALL_SHIPS                                             :All ships
+STR_GROUP_ALL_AIRCRAFTS                                         :All aircraft
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Add shared vehicles
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Remove all vehicles
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Train{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Road Vehicle{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Ship{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Aircraft
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Rename a group
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Replace Vehicles of "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Can't create group...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Can't delete this group...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Can't rename group...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Can't remove all vehicles from this group...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Can't add the vehicle to this group...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Can't add shared vehicles to group...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Groups - Click on a group to list all of its vehicles
+STR_GROUP_CREATE_TIP                                            :{BLACK}Click to create a group
+STR_GROUP_DELETE_TIP                                            :{BLACK}Delete the selected group
+STR_GROUP_RENAME_TIP                                            :{BLACK}Rename the selected group
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Click to protect this group from global autoreplace
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Profit this year: {GREEN}{CURRENCY} {BLACK}(last year: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit this year: {RED}{CURRENCY} {BLACK}(last year: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit this year: {GREEN}{CURRENCY} {BLACK}(last year: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Profit this year: {RED}{CURRENCY} {BLACK}(last year: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/brazilian_portuguese.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/brazilian_portuguese.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case m f
 ##gender m f
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Fora do mapa
@@ -1048,6 +1050,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Novo busca de caminho global (NPF, sobrepõe NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Multiplicador de peso para trens simulando trens pesados: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Permitir estações drive-through em ruas locais: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Permitir construção de estações adjacentes: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Permitir sempre aeroportos pequenos: {ORANGE}{STRING}
 
@@ -1100,6 +1103,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Desligado
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Velocidade do scrollwheel do mapa: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Pausar automaticamente ao inicar um novo jogo: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Usar a lista avançada de veículos: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Máximo de trens por jogador: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Máximo de automóveis por jogador: {ORANGE}{STRING}
@@ -1587,6 +1591,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Ferrovia com pré-sinais
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Ferrovia com sinais de saída
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Ferrovia com sinais combinados
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Remova a estação de trem antes
 
 
 
@@ -2016,6 +2021,8 @@
 STR_SV_STNAME_HELIPORT                                          :Heliporto de {STRING}
 STR_SV_STNAME_FOREST                                            :Floresta de {STRING}
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3191,3 +3198,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Alternar transparência para construções como estações, depósitos, pontos de controle e eletrificação da ferrovia
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Alternar transparência para pontes
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Alternar transparência para estruturas como faróis e antenas, talvez no futuro para efeitos visuais
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Agrupar {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Todos os trens
+STR_GROUP_ALL_ROADS                                             :Todos os automóveis
+STR_GROUP_ALL_SHIPS                                             :Todos os navios
+STR_GROUP_ALL_AIRCRAFTS                                         :Todas as aeronaves
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Adicionar veículos compartilhados
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Remover todos os veículos
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Trem{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Automóvel{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Navio{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Aeronave
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Renomear um grupo
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Substituir Veículos de "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Impossível criar grupo...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Impossível remover grupo...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Impossível renomear grupo...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Impossível remover todos os veículos desse grupo...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Impossível adicionar veículo a esse grupo
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Impossível adicionar veículos compartilhados a esse grupo...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Grupos - Clique em um grupo para listar seus veículos
+STR_GROUP_CREATE_TIP                                            :{BLACK}Clique para criar um grupo
+STR_GROUP_DELETE_TIP                                            :{BLACK}Remove o grupo selecionado
+STR_GROUP_RENAME_TIP                                            :{BLACK}Renomeia o grupo selecionado
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Clique para excluir esse grupo da substituição automática
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Lucros do ano: {GREEN}{CURRENCY} {BLACK}(ano passado: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Lucros do ano: {RED}{CURRENCY} {BLACK}(ano passado: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Lucros do ano {GREEN}{CURRENCY} {BLACK}(ano passado: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Lucros do ano: {RED}{CURRENCY} {BLACK}(ano passado {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/bulgarian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/bulgarian.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case accusative dative vocative nominative instrumental locative genitive
 ##gender мъжки женски среден
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Извън картата
@@ -1100,6 +1102,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Изклучен
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Scrollwheel скорост на картата: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Автоматична пауза стартирайки нова игра: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Използваи напредналиат списък на превозни средства: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Макс. влакове на играч: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Макс. брой коли на играч: {ORANGE}{STRING}
@@ -1134,7 +1137,10 @@
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}При влачене, поставяне на семафори всеки: {ORANGE}{STRING} плочка(и)
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Автоматично построй семафори преди: {ORANGE}{STRING}
 
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Грацкиа план "няма повече пътища" е невалиден в сценарий редакторат
 STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Избери грацки пътформат: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :няма повече пътища
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :default
 STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :по-добри пътища
 STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2х2 мрежа
 STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3х3 мрежа
@@ -2011,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Хелипорт
 STR_SV_STNAME_FOREST                                            :{STRING} Дървета
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3113,6 +3121,7 @@
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Мащаб предупреждение
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Прекаленото оразмеряване не е препорачително. Продължаване с генерацията?
 STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Грацки план предупреждение
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}Грацкиа план "няма повече пътища" не е препоръчан. Продължи със създаването?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Име на височинна карта:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Размер: {ORANGE}{NUM} x {NUM}
@@ -3185,3 +3194,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Използвай прозрачност за сгради като гари, депа, пътни точки и висящи жици
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Използвай прозрачност за мостове
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Използвай прозрачност за сгради като фарове и антени, може би в бъдеще за украси
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Група {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Всички влакове
+STR_GROUP_ALL_ROADS                                             :Всички пътни превозни средства
+STR_GROUP_ALL_SHIPS                                             :Всички кораби
+STR_GROUP_ALL_AIRCRAFTS                                         :Всички самолети
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Добави споделени превозни средства
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Премахни всички превозни средсва
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Влак{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Пътно Превозно Средство{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Кораб{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Самолет
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Преименовай група
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Замени Превозни средства на "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Групата неможе да бъде създадена...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Тази група неможе да бъде изтрита...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Групата неможе да бъде преименована...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Всички превозни средства немогат да бъдат премахнати от тази група...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Превозното средство неможе да се добави към тази група...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Поделени превозни средсва немогат да бъдат добавени към групата...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Групи - Щракни на група за да видиш списък на всички превозни средства от тази група
+STR_GROUP_CREATE_TIP                                            :{BLACK}Щракни да създадеш група
+STR_GROUP_DELETE_TIP                                            :{BLACK}Изтрий избраната група
+STR_GROUP_RENAME_TIP                                            :{BLACK}Преименувай избраната група
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Щракни да защитиш тази група от глобална автоматична замяна
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Печалба тази година: {GREEN}{CURRENCY} {BLACK}(предишната година: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Печалба тази година: {RED}{CURRENCY} {BLACK}(предишната година: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Печалба тази година: {GREEN}{CURRENCY} {BLACK}(предишната година: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Печалба тази година: {RED}{CURRENCY} {BLACK}(предишната година: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/czech.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/czech.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case nom gen dat acc voc loc ins big
 ##gender f m n
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Mimo okraj mapy
@@ -1104,6 +1106,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Nový globální algoritmus hledání cesty (NPF, nahradí NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Pro simulaci těžkých vlaků vynásobit hmotnost nákladu: {ORANGE}{STRING}x
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Povolit průjezdné zastávky na silnicích vlastněných obcemi: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Povolit stavění přilehlých stanic: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Malá letiště se budou moci stále stavět: {ORANGE}{STRING}
 
@@ -1156,6 +1159,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :nic
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Rychlost skrolovacího kolečka: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Zastavit automaticky hru při začínání nové hry: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Používat pokročilý seznam vozidel: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Maximum vlaků na hráče: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Maximum silničních vozidel na hráče: {ORANGE}{STRING}
@@ -1643,6 +1647,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Železniční trať s presignály
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Železniční trať s výstupními signály
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Železniční trať s kombinovanými signály
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Je nejprve nutno odstranit stanici
 
 
 
@@ -2070,6 +2075,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} heliport
 STR_SV_STNAME_FOREST                                            :{STRING} les
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3251,3 +3258,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Změna průhlednosti postavitelných objektů, jako stanic, kontrolních bodů a vedení
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Změna průhlednosti mostů
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Změna průhlednosti staveb jako majáků, vysílačů a doplňků (v budoucnosti)
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Skupina {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Všechny vlaky
+STR_GROUP_ALL_ROADS                                             :Všechna silniční vozidla
+STR_GROUP_ALL_SHIPS                                             :Všechny lodě
+STR_GROUP_ALL_AIRCRAFTS                                         :Všechna letadla
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Přidat sdílená vozidla
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Odstranit všechna vozidla
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} vlak{P "" y ů}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} silniční{P "" "" ch} vozid{P lo la el}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} lo{P ď dě dí}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} letad{P lo la el}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Přejmenovat skupinu
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Vyměnit vozidla "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Nelze vytvořit skupinu...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Nelze vymazat skupinu...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Nelze přejmenovat skupinu...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Nelze odstranit všechna vozidla ze skupiny...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Nelze přidat vozidlo do skupiny...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Nelze přidat sdílená vozidla do skupiny...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Skupiny - Kliknutím na skupinu se zobrazí seznam vozidel ve skupině
+STR_GROUP_CREATE_TIP                                            :{BLACK}Kliknutím vytvoříš skupinu
+STR_GROUP_DELETE_TIP                                            :{BLACK}Vymazat vybranou skupinu
+STR_GROUP_RENAME_TIP                                            :{BLACK}Přejmenovat vybranou skupinu
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Kliknutím nebude na tuto skupinu mít vliv automatická výměna vozidel
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Letošní příjem: {GREEN}{CURRENCY} {BLACK}(minulý rok: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Letošní příjem: {RED}{CURRENCY} {BLACK}(minulý rok: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Letošní příjem: {GREEN}{CURRENCY} {BLACK}(minulý rok: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Letošní příjem: {RED}{CURRENCY} {BLACK}(minulý rok: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/danish.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/danish.txt	Fri May 25 00:25:08 2007 +0000
@@ -385,7 +385,7 @@
 STR_SORT_BY_VALUE                                               :Værdi
 STR_SORT_BY_FACILITY                                            :Stationstype
 STR_SORT_BY_WAITING                                             :Værdi af ventende fragt
-STR_SORT_BY_RATING_MAX                                          :Fragtrangering
+STR_SORT_BY_RATING_MAX                                          :Fragtbedømmelse
 STR_ENGINE_SORT_ENGINE_ID                                       :Lokomotiv ID (klassisk)
 STR_ENGINE_SORT_COST                                            :Omkostning
 STR_ENGINE_SORT_POWER                                           :Drivmiddel
@@ -408,7 +408,7 @@
 STR_SEND_ROAD_VEHICLE_TO_DEPOT                                  :Send til værksted
 STR_SEND_SHIP_TO_DEPOT                                          :Send til skibsdok
 STR_SEND_AIRCRAFT_TO_HANGAR                                     :Send til hangar
-STR_SEND_FOR_SERVICING                                          :Send til service
+STR_SEND_FOR_SERVICING                                          :Send til eftersyn
 
 ############ range for months starts
 STR_0162_JAN                                                    :jan
@@ -458,7 +458,7 @@
 STR_018C_WINDOW_TITLE_DRAG_THIS                                 :{BLACK}Vinduestitel - træk her for at flytte vinduet
 STR_STICKY_BUTTON                                               :{BLACK}Marker dette vindue som ulukkeligt af 'Luk ALLE vinduer' tasten
 STR_RESIZE_BUTTON                                               :{BLACK}Klik og træk for at ændre vinduets størrelse
-STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Klik her for at gå til det nuværende default gemme/hente bibliotek
+STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Klik her for at gå til det nuværende standard gemme/hente bibliotek
 STR_018D_DEMOLISH_BUILDINGS_ETC                                 :{BLACK}Nedriv bygninger osv. på et stykke land
 STR_018E_LOWER_A_CORNER_OF_LAND                                 :{BLACK}Sænk et hjørne af landet
 STR_018F_RAISE_A_CORNER_OF_LAND                                 :{BLACK}Hæv et hjørne af landet
@@ -989,15 +989,15 @@
 # DON'T ADD OR REMOVE LINES HERE
 STR_TRAIN_HAS_TOO_FEW_ORDERS                                    :{WHITE}Tog {COMMA} har for få ordrer i sin odreliste
 STR_TRAIN_HAS_VOID_ORDER                                        :{WHITE}Tog {COMMA} har en ugyldig ordre
-STR_TRAIN_HAS_DUPLICATE_ENTRY                                   :{WHITE}Tog {COMMA} har dobbelt ordrer
+STR_TRAIN_HAS_DUPLICATE_ENTRY                                   :{WHITE}Tog {COMMA} har dobbelte ordrer
 STR_TRAIN_HAS_INVALID_ENTRY                                     :{WHITE}Tog {COMMA} har en ugyldig station i sin ordreliste
-STR_ROADVEHICLE_HAS_TOO_FEW_ORDERS                              :{WHITE}Køretøj {COMMA} har for få ordrer i sin ruteplan
+STR_ROADVEHICLE_HAS_TOO_FEW_ORDERS                              :{WHITE}Køretøj {COMMA} har for få ordrer i sin ordreliste
 STR_ROADVEHICLE_HAS_VOID_ORDER                                  :{WHITE}Køretøj {COMMA} har en ugyldig ordre
-STR_ROADVEHICLE_HAS_DUPLICATE_ENTRY                             :{WHITE}Køretøj {COMMA} har dobbelt ordrer
+STR_ROADVEHICLE_HAS_DUPLICATE_ENTRY                             :{WHITE}Køretøj {COMMA} har dobbelte ordrer
 STR_ROADVEHICLE_HAS_INVALID_ENTRY                               :{WHITE}Køretøj {COMMA} har en ugyldig station i sin ordreliste
 STR_SHIP_HAS_TOO_FEW_ORDERS                                     :{WHITE}Skib {COMMA} har for få ordrer i sin ordreliste
 STR_SHIP_HAS_VOID_ORDER                                         :{WHITE}Skib {COMMA} har en ugyldig ordre
-STR_SHIP_HAS_DUPLICATE_ENTRY                                    :{WHITE}Skib {COMMA} har dobbelt ordrer
+STR_SHIP_HAS_DUPLICATE_ENTRY                                    :{WHITE}Skib {COMMA} har dobbelte ordrer
 STR_SHIP_HAS_INVALID_ENTRY                                      :{WHITE}Skib {COMMA} har en ugyldig havn i sin ordreliste
 STR_AIRCRAFT_HAS_TOO_FEW_ORDERS                                 :{WHITE}Fly {COMMA} har for få ordrer i sin ordreliste
 STR_AIRCRAFT_HAS_VOID_ORDER                                     :{WHITE}Fly {COMMA} har en ugyldig ordre
@@ -1098,6 +1098,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Slået fra
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Rulleknap-hastighed på kort: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Sæt automatisk på pause når nyt spil startes: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Brug avanceret køretøjsliste: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Maks. antal tog per spiller: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Maks. antal køretøjer per spiller: {ORANGE}{STRING}
@@ -1254,7 +1255,7 @@
 STR_DRAG_DROP                                                   :{BLACK}Træk & slip
 STR_STATION_DRAG_DROP                                           :{BLACK}Byg en station vha. træk & slip
 STR_SELECT_STATION_CLASS_TIP                                    :{BLACK}Vælg hvilken stationstype, der skal vises
-STR_SELECT_STATION_TYPE_TIP                                     :{BLACK}Vælg hvilen stationstype du vil bygge
+STR_SELECT_STATION_TYPE_TIP                                     :{BLACK}Vælg hvilken stationstype du vil bygge
 
 STR_FAST_FORWARD                                                :{BLACK}Kør spillet hurtigere
 STR_MESSAGE_HISTORY                                             :{WHITE}Tidligere beskeder
@@ -1289,10 +1290,10 @@
 
 STR_INDUSTRY_TOO_CLOSE                                          :{WHITE}...for tæt på en anden industribygning
 
-STR_RAIL_REFIT_VEHICLE_TO_CARRY                                 :{BLACK}Ombyg toget til at køre med en anden slags last
+STR_RAIL_REFIT_VEHICLE_TO_CARRY                                 :{BLACK}Ombyg toget til at køre med en anden lasttype
 STR_RAIL_REFIT_VEHICLE                                          :{BLACK}Ombyg toget
-STR_RAIL_SELECT_TYPE_OF_CARGO_FOR                               :{BLACK}Vælg den slags last toget skal køre med
-STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED                             :{BLACK}Ombyg toget til at køre med den markerede slags last
+STR_RAIL_SELECT_TYPE_OF_CARGO_FOR                               :{BLACK}Vælg den lasttype toget skal køre med
+STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED                             :{BLACK}Ombyg toget til at køre med den markerede lasttype
 STR_RAIL_CAN_T_REFIT_VEHICLE                                    :{WHITE}Kan ikke ombygge toget...
 STR_CONFIG_PATCHES_SERVINT_ISPERCENT                            :{LTBLUE}Service intervaller er i procent: {ORANGE}{STRING}
 STR_CONFIG_GAME_PRODUCTION                                      :{WHITE}Skift produktion
@@ -1590,7 +1591,7 @@
 
 ##id 0x1800
 STR_1801_MUST_REMOVE_ROAD_FIRST                                 :{WHITE}Det er nødvendigt at fjerne vejen først
-STR_ROAD_WORKS_IN_PROGRESS                                      :{WHITE}Vejarbejde er i gang
+STR_ROAD_WORKS_IN_PROGRESS                                      :{WHITE}Vejarbejde i gang
 STR_1802_ROAD_CONSTRUCTION                                      :{WHITE}Vejkonstruktion
 STR_1803_SELECT_ROAD_BRIDGE                                     :{WHITE}Vælg vejbro
 STR_1804_CAN_T_BUILD_ROAD_HERE                                  :{WHITE}Kan ikke bygge vej her...
@@ -1703,7 +1704,7 @@
 STR_2051_BUILD_A_STATUE_IN_HONOR                                :{WHITE}{STRING}{}{YELLOW} Byg en statue til ære for dit selskab.{} Pris: {CURRENCY}
 STR_2052_FUND_THE_CONSTRUCTION_OF                               :{WHITE}{STRING}{}{YELLOW} Betal for opførelse af forretningsbygninger i byen.{}  Pris: {CURRENCY}
 STR_2053_BUY_1_YEAR_S_EXCLUSIVE                                 :{WHITE}{STRING}{}{YELLOW} Køb et års eksklusive rettigheder til transport i byen. De lokale myndigheder vil kun tillade passagerer og last at bruge dine stationer.{} Prist: {CURRENCY}
-STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC                         :{WHITE}{STRING}{}{YELLOW} Bestik de lokale myndigheder til at hæve din bedømmelse, med sandsynlighed for en stor straf hvis det bliver opdaget.{}  Pris: {CURRENCY}
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC                         :{WHITE}{STRING}{}{YELLOW} Bestik de lokale myndigheder til at hæve din bedømmelse, med risiko for en stor straf hvis det bliver opdaget.{}  Pris: {CURRENCY}
 STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING                       :{BIGFONT}{BLACK}Trafikkaos i byen {TOWN}!{}{}Vejfornyelse betalt af {COMPANY} forårsager 6 måneders kaos i trafikken!
 STR_2056                                                        :{TINYFONT}{WHITE}{TOWN}
 STR_2057                                                        :{ORANGE}{TOWN}{BLACK} ({COMMA})
@@ -2012,6 +2013,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Helikopterplads
 STR_SV_STNAME_FOREST                                            :{STRING} Skov
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2148,7 +2151,7 @@
 STR_7037_PRESIDENT                                              :{WHITE}{PLAYERNAME}{}{GOLD}(Direktør)
 STR_7038_INAUGURATED                                            :{GOLD}Indviet: {WHITE}{NUM}
 STR_7039_VEHICLES                                               :{GOLD}Køretøjer:
-STR_TRAINS                                                      :{WHITE}{COMMA} tog
+STR_TRAINS                                                      :{WHITE}{COMMA} tog{P "" e}
 STR_ROAD_VEHICLES                                               :{WHITE}{COMMA} køretøj{P "" er}
 STR_AIRCRAFT                                                    :{WHITE}{COMMA} fly
 STR_SHIPS                                                       :{WHITE}{COMMA} skib{P "" e}
@@ -2726,7 +2729,7 @@
 
 STR_REFIT_ROAD_VEHICLE_TO_CARRY                                 :{BLACK}Ombyg vejkøretøj til at laste en anden type last
 STR_REFIT_ROAD_VEHICLE                                          :{BLACK}Ombyg lastbil
-STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED                     :{BLACK}Ombyg vejkøretøjet til at laste den markede type last
+STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED                     :{BLACK}Ombyg vejkøretøjet til at laste den markerede type last
 STR_REFIT_ROAD_VEHICLE_CAN_T                                    :{WHITE}Kan ikke ombygge vejkøretøj
 STR_ROAD_SELECT_TYPE_OF_CARGO_FOR                               :{BLACK}Vælg lasttype som lastbilen skal transportere
 
@@ -2987,7 +2990,7 @@
 STR_SCHEDULED_AIRCRAFT                                          :{WHITE}{STATION} - {COMMA} Fly
 STR_SCHEDULED_SHIPS                                             :{WHITE}{STATION} - {COMMA} Skib{P "" e}
 
-STR_SCHEDULED_TRAINS_TIP                                        :{BLACK}Vis alle tog, som har denne station i deres ruteplan
+STR_SCHEDULED_TRAINS_TIP                                        :{BLACK}Vis alle toge, som har denne station i deres ruteplan
 STR_SCHEDULED_ROAD_VEHICLES_TIP                                 :{BLACK}Vis alle køretøjer, som har denne station i deres ruteplan
 STR_SCHEDULED_AIRCRAFT_TIP                                      :{BLACK}Vis alle fly, som har denne lufthavn i deres ruteplan
 STR_SCHEDULED_SHIPS_TIP                                         :{BLACK}Vis alle skibe, som har denne station i deres ruteplan
@@ -3024,7 +3027,7 @@
 STR_NOT_REPLACING                                               :{BLACK}Udskifter ikke
 STR_NOT_REPLACING_VEHICLE_SELECTED                              :{BLACK}Intet køretøj valgt
 STR_REPLACE_HELP_LEFT_ARRAY                                     :{BLACK}Vælg en køretøjstype, som du ønsker udskiftet
-STR_REPLACE_HELP_RIGHT_ARRAY                                    :{BLACK}Vælg en køretøjstype, som du ønker at få i stedet for den type, du  har valgt i venste side
+STR_REPLACE_HELP_RIGHT_ARRAY                                    :{BLACK}Vælg en køretøjstype, som du ønker benyttet i stedet for den type, du  har valgt i venste side
 STR_REPLACE_HELP_STOP_BUTTON                                    :{BLACK}Tryk for at stoppe udskiftningen at den køretøjstype, som du har valgt til venstre
 STR_REPLACE_HELP_START_BUTTON                                   :{BLACK}Tryk for at begynde at udskifte køretøjstypen til venstre med køretøjstypen til højre
 STR_REPLACE_HELP_RAILTYPE                                       :{BLACK}Vælg den skinnetype, hvor du vil udskifte lokomotiver
@@ -3033,10 +3036,10 @@
 STR_REPLACE_REMOVE_WAGON                                        :{BLACK}Fjern vogn: {ORANGE}{SKIP}{STRING}
 STR_REPLACE_REMOVE_WAGON_HELP                                   :{BLACK}Få autoudskift til at bevare længden af tog ved at fjerne vogne (startende fra fronten), hvis autoudskiftningen gør toget længere.
 STR_REPLACE_ENGINE_WAGON_SELECT                                 :{BLACK}Udskifter: {ORANGE}{SKIP}{SKIP}{STRING}
-STR_REPLACE_ENGINE_WAGON_SELECT_HELP                            :{BLACK} EKSPERIMENTEL EGENSKAB {}Skift imellem lokomotiv- og vogn-udskiftningsvindue.{}Vognudskiftning vil kun finde sted hvis den nye vogn kan ændres til at transportere samme godstype some den gamle vogn. Dette bliver checket for hver vogn, når udskiftningen finder sted.
-STR_RAIL_VEHICLE_NOT_AVAILABLE                                  :{WHITE}Tog er ikke tilgængelig
-STR_ROAD_VEHICLE_NOT_AVAILABLE                                  :{WHITE}Vejkøretøj er ikke tilgængelig
-STR_SHIP_NOT_AVAILABLE                                          :{WHITE}Skib er ikke tilgængelig
+STR_REPLACE_ENGINE_WAGON_SELECT_HELP                            :{BLACK} EKSPERIMENTEL EGENSKAB {}Skift imellem lokomotiv- og vogn-udskiftningsvindue.{}Vognudskiftning vil kun finde sted hvis den nye vogn kan ændres til at transportere samme godstype som den gamle vogn. Dette bliver checket for hver vogn, når udskiftningen finder sted.
+STR_RAIL_VEHICLE_NOT_AVAILABLE                                  :{WHITE}Tog er ikke tilgængeligt
+STR_ROAD_VEHICLE_NOT_AVAILABLE                                  :{WHITE}Vejkøretøj er ikke tilgængeligt
+STR_SHIP_NOT_AVAILABLE                                          :{WHITE}Skib er ikke tilgængeligt
 STR_AIRCRAFT_NOT_AVAILABLE                                      :{WHITE}Fly er ikke tilgængelig
 
 STR_ENGINES                                                     :Lokomotiver
@@ -3187,3 +3190,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Skift gennemsigtighed for konstruktioner som stationer, værksteder, kontrolsteder og køreledninger
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Skift gennemsigtighed for broer
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Skift gennemsigtighed for strukturer som fyrtårne og antenner, og måske i fremtiden for øjeguf
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Gruppe {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Alle toge
+STR_GROUP_ALL_ROADS                                             :Alle vejkøretøjer
+STR_GROUP_ALL_SHIPS                                             :Alle skibe
+STR_GROUP_ALL_AIRCRAFTS                                         :Alle fly
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Tilføj delte køretøjer
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Fjern alle køretøjer
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Tog{P "" e}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Vejkøretøj{P "" er}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Skib{P "" e}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Fly
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Omdøb en gruppe
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Udskift køretøjer i "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Kan ikke oprette gruppe...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Kan ikke slette denne gruppe...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Kan ikke omdøbe gruppe...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Kan ikke fjerne alle køretøjer fra denne gruppe...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Kan ikke tilføje køretøjet til denne gruppe...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Kan ikke tilføje delte køretøjer til gruppe...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Grupper - klik på en gruppe for at vise alle køretøjer i gruppen
+STR_GROUP_CREATE_TIP                                            :{BLACK}Klik for at oprette en gruppe
+STR_GROUP_DELETE_TIP                                            :{BLACK}Slet den valgte gruppe
+STR_GROUP_RENAME_TIP                                            :{BLACK}Omdøb den valgte gruppe
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Klik for at beskytte denne gruppe mod global auto-udskiftning
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Afkast i indeværende år: {GREEN}{CURRENCY} {BLACK}(sidste år: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Afkast i indeværende år: {RED}{CURRENCY} {BLACK}(sidste år: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Afkast i indeværende år: {GREEN}{CURRENCY} {BLACK}(sidste år: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Afkast i indeværende år: {RED}{CURRENCY} {BLACK}(sidste år: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/dutch.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/dutch.txt	Fri May 25 00:25:08 2007 +0000
@@ -3,6 +3,8 @@
 ##isocode nl_NL
 ##plural 0
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Buiten de kaart
@@ -1046,6 +1048,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Nieuwe globale routeplanner (NPF, voorkeur over NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Gewichtsverhouding voor vracht om zware treinen te simuleren: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Laat toe dat doorrij wegstops worden geplaatst op door stad beheerde wegen: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Bouwen van aangrenzende stations toestaan: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Altijd kleine vliegvelden toestaan: {ORANGE}{STRING}
 
@@ -1098,6 +1101,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Uit
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Kaart muiswiel snelheid: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automatisch pauzeren wanneer je een nieuw spel start: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Gebruik de geavanceerde voertuigenlijst: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Maximaal aantal treinen per speler: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Maximaal aantal wegvoertuigen per speler: {ORANGE}{STRING}
@@ -1137,8 +1141,8 @@
 STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :geen wegen
 STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :standaard
 STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :betere wegen
-STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2x2 rooster
-STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3x3 rooster
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2x2 raster
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3x3 raster
 
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Positie van algemene toolbar: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Links
@@ -1585,6 +1589,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Spoor met voorseinen
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Spoor met uitgangseinen
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Spoor met combinatieseinen
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Treinstation moet eerst verwijderd worden
 
 
 
@@ -2012,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Helihaven
 STR_SV_STNAME_FOREST                                            :{STRING} Bossen
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3113,7 +3120,7 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Verander begin jaar
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Schaal waarschuwing
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Het aanpassen van de grootte van een bronkaar is niet aan te bevelen. Toch doorgaan?
-STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Stadsindelingwaarschuwing
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Stadsindelingswaarschuwing
 STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}De stadsindeling "geen wegen" is niet aanbevolen. Doorgaan met aanmaken?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Hoogtekaart naam:
@@ -3187,3 +3194,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Wissel doorzichtigheid voor gebouwen zoals stations, depots, waypoints en bovenleiding
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Wissel doorzichtigheid voor bruggen
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Wissel doorzichtigheid voor structuren zoals vuurtoren en antennes, in de toekomst misschien voor eyecandy
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Groep {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Alle treinen
+STR_GROUP_ALL_ROADS                                             :Alle voertuigen
+STR_GROUP_ALL_SHIPS                                             :Alle schepen
+STR_GROUP_ALL_AIRCRAFTS                                         :Alle vliegtuigen
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Toevoegen gedeelde voertuigen
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Verwijder alle voertuigen
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Trein{P "" en}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Weg Voertuig{P "" en}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Schip{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Vliegtuig
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Hernoem een groep
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Vervang voertuigen van "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Kan groep niet maken...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Kan deze groep niet verwijderen...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Kan deze groep niet hernoemen...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Kan niet alle voertuigen van deze groep verwijderen...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Kan niet alle voertuigen aan deze groep toevoegen...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Kan niet alle gedeelde voertuigen aan deze groep toevoegen...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Groepen - Klik op een groep voor een lijst van alle voertuigen in deze groep
+STR_GROUP_CREATE_TIP                                            :{BLACK}Klik om een groep te maken
+STR_GROUP_DELETE_TIP                                            :{BLACK}Verwijder de geselecteerde groep
+STR_GROUP_RENAME_TIP                                            :{BLACK}Hernoem de geselecteerde groep
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Klik om deze groep te beschermen tegen globaal automatisch vervangen
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Winst dit jaar: {GREEN}{CURRENCY} {BLACK}(vorig jaar: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Winst dit jaar: {RED}{CURRENCY} {BLACK}(vorig jaar: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Winst dit jaar: {GREEN}{CURRENCY} {BLACK}(vorig jaar: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Winst dit jaar: {RED}{CURRENCY} {BLACK}(vorig jaar: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/english.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/english.txt	Fri May 25 00:25:08 2007 +0000
@@ -3,6 +3,8 @@
 ##isocode en_GB
 ##plural 0
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Off edge of map
@@ -1046,6 +1048,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}New global pathfinding (NPF, overrides NTP): {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Always allow small airports: {ORANGE}{STRING1}
 
@@ -1098,6 +1101,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Off
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Map scrollwheel speed: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automatically pause when starting a new game: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Use the advanced vehicle list: {ORANGE}{STRING1}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Max trains per player: {ORANGE}{STRING1}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Max road vehicles per player: {ORANGE}{STRING1}
@@ -1585,6 +1589,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Railway track with pre-signals
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Railway track with exit-signals
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Railway track with combo-signals
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Must remove railway station first
 
 
 
@@ -2012,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING1} Heliport
 STR_SV_STNAME_FOREST                                            :{STRING1} Forest
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3187,3 +3194,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Toggle transparency for buildables like stations, depots, waypoints and catenary
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Toggle transparency for bridges
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Toggle transparency for structures like lighthouses and antennas, maybe in future for eyecandy
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Group {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :All trains
+STR_GROUP_ALL_ROADS                                             :All road vehicles
+STR_GROUP_ALL_SHIPS                                             :All ships
+STR_GROUP_ALL_AIRCRAFTS                                         :All aircraft
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Add shared vehicles
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Remove all vehicles
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Train{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Road Vehicle{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Ship{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Aircraft
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Rename a group
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Replace Vehicles of "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Can't create group...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Can't delete this group...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Can't rename group...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Can't remove all vehicles from this group...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Can't add the vehicle to this group...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Can't add shared vehicles to group...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Groups - Click on a group to list all vehicles of this group
+STR_GROUP_CREATE_TIP                                            :{BLACK}Click to create a group
+STR_GROUP_DELETE_TIP                                            :{BLACK}Delete the selected group
+STR_GROUP_RENAME_TIP                                            :{BLACK}Rename the selected group
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Click to protect this group from global autoreplace
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Profit this year: {GREEN}{CURRENCY} {BLACK}(last year: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit this year: {RED}{CURRENCY} {BLACK}(last year: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit this year: {GREEN}{CURRENCY} {BLACK}(last year: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Profit this year: {RED}{CURRENCY} {BLACK}(last year: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/estonian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/estonian.txt	Fri May 25 00:25:08 2007 +0000
@@ -1231,6 +1231,15 @@
 STR_CONFIG_PATCHES_ALLOW_SHARES                                 :{LTBLUE}Luba teiste ettevõtete aktsiate ostmine
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}Venitades paigutatud signaaltulede tihedus: {ORANGE}{STRING} ühik(ut)
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Ehita semaforid automaatselt enne: {ORANGE}{STRING}
+
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Stsenaariumiredaktor ei tunnista "ilma teedeta" linnaplaneeringut
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Vali linnale teeplaan: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :ilma teedeta
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :tavalised
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :paremad teed
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2x2 ruudustik
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3x3 ruudustik
+
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Tööriistariba asukoht: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Vasakul
 STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER                           :Keskel
@@ -2138,6 +2147,7 @@
 ############ range for difficulty settings ends
 
 STR_26816_NONE                                                  :Pole
+STR_NUM_VERY_LOW                                                :Väga madal
 STR_6816_LOW                                                    :Madal
 STR_6817_NORMAL                                                 :Harilik
 STR_6818_HIGH                                                   :Kõrge
@@ -3203,6 +3213,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Muuda algusaastat
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Skaala hoiatus
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Kaardi suuruse muutmine pole soovitatav. Jätka?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Linnaplaneerimise hoiatus
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}Linnaplaneeringut "ilma teedeta" ei ole soovitatav kasutada. Jätkata selle tekitamisega?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Kõrgusekaardi nimi:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Suurus: {ORANGE}{NUM} x {NUM}
--- a/src/lang/french.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/french.txt	Fri May 25 00:25:08 2007 +0000
@@ -4,6 +4,8 @@
 ##plural 2
 ##gender m m2 f
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Hors limites
@@ -250,7 +252,7 @@
 STR_0119_TOFFEE_QUARRY                                          :{BLACK}{TINYFONT}Carrière de Caramel
 STR_011A_SUGAR_MINE                                             :{BLACK}{TINYFONT}Mine de Sucre
 STR_011B_RAILROAD_STATION                                       :{BLACK}{TINYFONT}Gare ferroviaire
-STR_011C_TRUCK_LOADING_BAY                                      :{BLACK}{TINYFONT}Zone de Chargement
+STR_011C_TRUCK_LOADING_BAY                                      :{BLACK}{TINYFONT}Aire de chargement
 STR_011D_BUS_STATION                                            :{BLACK}{TINYFONT}Arrêt d'autobus
 STR_011E_AIRPORT_HELIPORT                                       :{BLACK}{TINYFONT}Aéroport/Héliport
 STR_011F_DOCK                                                   :{BLACK}{TINYFONT}Port maritime
@@ -1047,6 +1049,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Nouvelle recherche de chemin global (NPF, écrase NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Multiplier le poid pour les trains fret (simule des trains lourds): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Autoriser les arrêts de bus sur les routes des municipalités: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Autoriser la construction de stations adjacentes: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Toujours permettre les petits aéroports: {ORANGE}{STRING}
 
@@ -1099,6 +1102,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Désactivé
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Vitesse de défilement avec molette: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Pause automatique en début de nouvelle partie: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Utiliser la liste de véhicules avancée: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Nombre de trains max. par joueur: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Nombre de véhicules routiers max. par joueur: {ORANGE}{STRING}
@@ -1553,7 +1557,7 @@
 STR_1004_TOO_HIGH                                               :{WHITE}Trop élevé
 STR_1005_NO_SUITABLE_RAILROAD_TRACK                             :{WHITE}Aucuns rails convenables
 STR_1007_ALREADY_BUILT                                          :{WHITE}...déjà construit
-STR_1008_MUST_REMOVE_RAILROAD_TRACK                             :{WHITE}Doit d'abord enlever les rails
+STR_1008_MUST_REMOVE_RAILROAD_TRACK                             :{WHITE}Vous devez d'abord enlever les rails
 STR_100A_RAILROAD_CONSTRUCTION                                  :{WHITE}Construction de voie ferrée
 STR_TITLE_ELRAIL_CONSTRUCTION                                   :{WHITE}Construction de voie ferrée électrifiée
 STR_100B_MONORAIL_CONSTRUCTION                                  :{WHITE}Construction de Monorail
@@ -1586,11 +1590,12 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Rails avec des pré-signaux
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Rails avec des signaux de sortie
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Rails avec des signaux combinés
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Vous devez d'abord retirer la gare
 
 
 
 ##id 0x1800
-STR_1801_MUST_REMOVE_ROAD_FIRST                                 :{WHITE}Doit d'abord retirer la route
+STR_1801_MUST_REMOVE_ROAD_FIRST                                 :{WHITE}Vous devez d'abord retirer la route
 STR_ROAD_WORKS_IN_PROGRESS                                      :{WHITE}Route en travaux
 STR_1802_ROAD_CONSTRUCTION                                      :{WHITE}Construction routière
 STR_1803_SELECT_ROAD_BRIDGE                                     :{WHITE}Choisir Pont Routier
@@ -1599,12 +1604,12 @@
 STR_1806_ROAD_DEPOT_ORIENTATION                                 :{WHITE}Orientation du dépôt
 STR_1807_CAN_T_BUILD_ROAD_VEHICLE                               :{WHITE}Impossible de construire un dépôt routier ici...
 STR_1808_CAN_T_BUILD_BUS_STATION                                :{WHITE}Impossible de construire un arrêt d'autobus...
-STR_1809_CAN_T_BUILD_TRUCK_STATION                              :{WHITE}Impossible de construire une station de camions...
+STR_1809_CAN_T_BUILD_TRUCK_STATION                              :{WHITE}Impossible de construire une aire de chargement...
 STR_180A_ROAD_CONSTRUCTION                                      :Construction routière
 STR_180B_BUILD_ROAD_SECTION                                     :{BLACK}Construire une section de route
 STR_180C_BUILD_ROAD_VEHICLE_DEPOT                               :{BLACK}Construire un dépôt routier (pour construire et entretenir les véhicules routiers)
 STR_180D_BUILD_BUS_STATION                                      :{BLACK}Construire un arrêt d'autobus
-STR_180E_BUILD_TRUCK_LOADING_BAY                                :{BLACK}Construire une station de camions
+STR_180E_BUILD_TRUCK_LOADING_BAY                                :{BLACK}Construire une aire de chargement
 STR_180F_BUILD_ROAD_BRIDGE                                      :{BLACK}Construire un pont routier
 STR_1810_BUILD_ROAD_TUNNEL                                      :{BLACK}Construire un tunnel routier
 STR_1811_TOGGLE_BUILD_REMOVE_FOR                                :{BLACK}Basculer construire/détruire routes
@@ -1779,15 +1784,15 @@
 STR_3040_NOW_ACCEPTS                                            :{WHITE}{STATION} accepte désormais: {STRING}
 STR_3041_NOW_ACCEPTS_AND                                        :{WHITE}{STATION} accepte désormais: {STRING} et {STRING}
 STR_3042_BUS_STATION_ORIENTATION                                :{WHITE}Arrêt d'autobus
-STR_3043_TRUCK_STATION_ORIENT                                   :{WHITE}Station de camions
-STR_3046_MUST_DEMOLISH_BUS_STATION                              :{WHITE}Détruire d'abord l'arrêt d'autobus
-STR_3047_MUST_DEMOLISH_TRUCK_STATION                            :{WHITE}Détruisez d'abord la station
+STR_3043_TRUCK_STATION_ORIENT                                   :{WHITE}Aire de chargement
+STR_3046_MUST_DEMOLISH_BUS_STATION                              :{WHITE}Vous devez d'abord détruire l'arrêt d'autobus
+STR_3047_MUST_DEMOLISH_TRUCK_STATION                            :{WHITE}Vous devez d'abord détruire l'aire de chargement
 STR_3048_STATIONS                                               :{WHITE}{COMPANY} - {COMMA} Station{P "" s}
 STR_3049_0                                                      :{YELLOW}{STATION} {STATIONFEATURES}
 STR_304A_NONE                                                   :{YELLOW}- Aucun -
 STR_304B_SITE_UNSUITABLE                                        :{WHITE}...l'endroit ne convient pas
 STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK                              :{WHITE}Trop près d'un autre port
-STR_304D_MUST_DEMOLISH_DOCK_FIRST                               :{WHITE}Détruisez d'abord le port
+STR_304D_MUST_DEMOLISH_DOCK_FIRST                               :{WHITE}Vous devez d'abord détruire le port
 STR_304E_SELECT_RAILROAD_STATION                                :{BLACK}Choisir l'orientation de la gare ferroviaire
 STR_304F_SELECT_NUMBER_OF_PLATFORMS                             :{BLACK}Choix du nombre de voies
 STR_3050_SELECT_LENGTH_OF_RAILROAD                              :{BLACK}Choisir la longueur de la gare
@@ -1924,7 +1929,7 @@
 STR_5001_ROAD_VEHICLE_IN_TUNNEL                                 :{WHITE}Véhicule dans le tunnel
 STR_5003_ANOTHER_TUNNEL_IN_THE_WAY                              :{WHITE}Autre tunnel présent
 STR_5005_UNABLE_TO_EXCAVATE_LAND                                :{WHITE}Impossible de creuser pour faire déboucher le tunnel
-STR_5006_MUST_DEMOLISH_TUNNEL_FIRST                             :{WHITE}Vous devez démolir le tunnel avant
+STR_5006_MUST_DEMOLISH_TUNNEL_FIRST                             :{WHITE}Vous devez d'abord démolir le tunnel
 STR_5007_MUST_DEMOLISH_BRIDGE_FIRST                             :{WHITE}Vous devez d'abord démolir le pont
 STR_5008_CANNOT_START_AND_END_ON                                :{WHITE}Impossible de commencer et de terminer au même endroit
 STR_5009_LEVEL_LAND_OR_WATER_REQUIRED                           :{WHITE}Crevasse ou eau requise sous le pont
@@ -2013,6 +2018,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Héliport
 STR_SV_STNAME_FOREST                                            :{STRING} Forêt
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2743,7 +2750,7 @@
 STR_CLONE_SHIP                                                  :{BLACK}Copier Navire
 STR_CLONE_SHIP_INFO                                             :{BLACK}Effectuer la copie d'un navire. Ctrl-clic partagera les ordres
 STR_CLONE_SHIP_DEPOT_INFO                                       :{BLACK}Effectuer la copie d'un navire. Cliquer ici puis sur un navire dans ou hors d'un dépôt. Ctrl-clic partagera les ordres
-STR_980B_SHIP_MUST_BE_STOPPED_IN                                :{WHITE}Navire doit être arrêté au dépôt
+STR_980B_SHIP_MUST_BE_STOPPED_IN                                :{WHITE}Le navire doit être arrêté au dépôt
 STR_980C_CAN_T_SELL_SHIP                                        :{WHITE}Impossible de vendre navire...
 STR_980D_CAN_T_BUILD_SHIP                                       :{WHITE}Impossible de construire navire...
 STR_980E_SHIP_IN_THE_WAY                                        :{WHITE}Navire présent
@@ -2833,7 +2840,7 @@
 STR_A017_AIRCRAFT_IS_IN_FLIGHT                                  :{WHITE}L'aéronef est en vol
 STR_A019_CAPACITY                                               :{BLACK}Capacité: {LTBLUE}{CARGO}, {CARGO}
 STR_A01A_CAPACITY                                               :{BLACK}Capacité: {LTBLUE}{CARGO}
-STR_A01B_AIRCRAFT_MUST_BE_STOPPED                               :{WHITE}Aéronef doit être arrêté au hangar
+STR_A01B_AIRCRAFT_MUST_BE_STOPPED                               :{WHITE}L'aéronef doit être arrêté au hangar
 STR_A01C_CAN_T_SELL_AIRCRAFT                                    :{WHITE}Impossible de vendre l'aéronef...
 STR_A01D_AIRPORT_CONSTRUCTION                                   :Construction d'aéroport
 STR_A01E_BUILD_AIRPORT                                          :{BLACK}Construire un aéroport
@@ -3188,3 +3195,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Transparence des éléments constructibles tels que stations, dépôts, points de contrôle et caténaire
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Transparence des ponts
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Transparence des structures telles que phares et antennes
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Groupe {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Tous les trains
+STR_GROUP_ALL_ROADS                                             :Tous les véhicules routiers
+STR_GROUP_ALL_SHIPS                                             :Tous les navires
+STR_GROUP_ALL_AIRCRAFTS                                         :Tous les aéronefs
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Ajouter des véhicules partagés
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Retirer tous les véhicules
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Train{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Véhicule{P "" s} routier{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Navire{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Aéronef{P "" s}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Renommer un groupe
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Remplacer les véhicules de "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Impossible de créer le groupe...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Impossible de supprimer ce groupe...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Impossible de renommer le groupe...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Impossible de retirer tous les véhicules de ce groupe...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Impossible d'ajouter le véhicule à ce groupe...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Impossible d'ajouter les véhicules partagés à ce groupe...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Groupes - Cliquer sur un groupe pour lister tous les véhicules de ce groupe
+STR_GROUP_CREATE_TIP                                            :{BLACK}Cliquer pour créer un groupe
+STR_GROUP_DELETE_TIP                                            :{BLACK}Supprimer le groupe sélectionné
+STR_GROUP_RENAME_TIP                                            :{BLACK}Renommer le groupe sélectionné
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Cliquer pour protéger ce groupe contre l'auto-remplacement global
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Profit cette année: {GREEN}{CURRENCY} {BLACK}(an dernier: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit cette année: {RED}{CURRENCY} {BLACK}(an dernier: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Profit cette année: {GREEN}{CURRENCY} {BLACK}(an dernier: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Profit cette année: {RED}{CURRENCY} {BLACK}(an dernier: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/german.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/german.txt	Fri May 25 00:25:08 2007 +0000
@@ -2013,6 +2013,7 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Heliport
 STR_SV_STNAME_FOREST                                            :{STRING} Wald
 
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3188,3 +3189,28 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Verändere die Transparenz für Gebäude wie Bahnhöfe, Depots, Wegpunkte und Oberleitung
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Verändere die Transparenz für Brücken
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Verändere die Transparenz für Bauten wie Leuchttürme und Antennen, evtl. in der Zukunft auch für Sehenswürdigkeiten
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Gruppe {COMMA}
+STR_GROUP_ALL_TRAINS                                            :Alle Züge
+STR_GROUP_ALL_ROADS                                             :Alle Straßenfahrzeuge
+STR_GROUP_ALL_SHIPS                                             :Alle Schiffe
+STR_GROUP_ALL_AIRCRAFTS                                         :Alle Flugzeuge
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Entferne alle Fahrzeuge
+
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Gruppe umbenennen
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Kann Gruppe nicht erstellen...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Kann diese Gruppe nicht löschen...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Kann Gruppe nicht umbenennen...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Kann nicht alle Fahrzeuge dieser Gruppe entfernen...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Kann das Fahrzeug nicht zu dieser Gruppe hinzufügen...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Gruppen - Klicke auf eine Gruppe für eine Liste aller Fahrzeuge der Gruppe
+STR_GROUP_CREATE_TIP                                            :{BLACK}Klicken um eine Gruppe zu erstellen
+STR_GROUP_DELETE_TIP                                            :{BLACK}Die ausgewählte Gruppe löschen
+STR_GROUP_RENAME_TIP                                            :{BLACK}Die ausgewählte Gruppe umbenennen
+
+
+########
--- a/src/lang/hungarian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/hungarian.txt	Fri May 25 00:25:08 2007 +0000
@@ -4,6 +4,8 @@
 ##plural 1
 ##case t ba
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Kilóg a térképről
@@ -1112,6 +1114,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Új útvonalkereső (NPF, felülbírálja az NTP-t): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Tömegszorzó tehervonatoknak (szimulációs célból): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Áthajtható állomások engedélyezése városi utakra: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Érintkező állomások építésének engedélyezése: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Mindig engedélyezze a kis repülőtereket: {ORANGE}{STRING}
 
@@ -1164,6 +1167,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Ki
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Scrollgomb sebessége a térképen: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automatikus pause-mode új játék esetén: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Továbbfejlesztett járműlista használata: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Maximum vonat játékosonként: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Maximum közúti jármű játékosonként: {ORANGE}{STRING}
@@ -1651,6 +1655,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Vasúti sin előrejelző szemaforral
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Vasúti sin kijáratjelző szemaforral
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Vasúti sin vegyes szemaforral
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Előbb a vasútállomást le kell rombolni
 
 
 
@@ -2115,6 +2120,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING}i helikopter-leszálló
 STR_SV_STNAME_FOREST                                            :{STRING}i erdőség
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3290,3 +3297,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Átkapcsolni az építhető elemekre (állomások, depók, útipontok és felsővezeték)
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Átkapcsolni a hidakra
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Átkapcsolni egyéb épületekre, mint világítótorony és antennák (esetleg egyéb jövőbeni díszek)
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :{COMMA} csoport
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Összes vonat
+STR_GROUP_ALL_ROADS                                             :Összes közúti jármű
+STR_GROUP_ALL_SHIPS                                             :Összes hajó
+STR_GROUP_ALL_AIRCRAFTS                                         :Összes repülő
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Megosztott jármű hozzáadása
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Összes jármű eltávolítása
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} vonat
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} közúti jármű
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} hajó
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} repülő
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Csoport átnevezése
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}A(z) "{GROUP}" csoport járműveinek lecserélése
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Csoport létrehozás sikertelen...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Csoport törlése sikertelen...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Csoport átnevezése sikertelen...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Csoport járműveinek törlése sikertelen...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Jármű hozzáadása a csoporthoz sikertelen...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Megosztott jármű csoporthoz való hozzáadása sikertelen...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Csoportok - Kattints a csoport nevére a járművek listázásához
+STR_GROUP_CREATE_TIP                                            :{BLACK}Csoport létrehozásához kattints ide
+STR_GROUP_DELETE_TIP                                            :{BLACK}Kijelölt csoport törlése
+STR_GROUP_RENAME_TIP                                            :{BLACK}Kijelölt csoport átnevezése
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Csoport automata csere alóli mentességének beállításához kattints ide
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Idei profit: {GREEN}{CURRENCY} {BLACK}(tavalyi: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Idei profit: {RED}{CURRENCY} {BLACK}(tavalyi: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Idei profit: {GREEN}{CURRENCY} {BLACK}(tavalyi: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Idei profit: {RED}{CURRENCY} {BLACK}(tavalyi: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/italian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/italian.txt	Fri May 25 00:25:08 2007 +0000
@@ -1100,6 +1100,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Off
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Velocità rotellina mappa: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Metti in pausa all'inizio di una nuova partita: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Utilizza la lista veicoli avanzata: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Max treni per giocatore: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Max automezzi per giocatore: {ORANGE}{STRING}
@@ -2014,6 +2015,8 @@
 STR_SV_STNAME_HELIPORT                                          :Eliporto di {STRING}
 STR_SV_STNAME_FOREST                                            :{STRING} Foresta
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3189,3 +3192,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Attiva/disattiva la trasparenza delle strutture edificabili come stazioni, depositi, waypoint e catenarie
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Attiva/disattiva la trasparenza dei ponti
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Attiva/disattiva la trasparenza di strutture come fari, antenne e altri futuri oggetti decorativi
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Gruppo {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Tutti i treni
+STR_GROUP_ALL_ROADS                                             :Tutti gli automezzi
+STR_GROUP_ALL_SHIPS                                             :Tutte le navi
+STR_GROUP_ALL_AIRCRAFTS                                         :Tutti gli aeromobili
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Aggiungi veicoli condivisi
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Rimuovi tutti i veicoli
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} tren{P o i}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} automezz{P o i}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} nav{P e i}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} aeromobil{P e i}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Rinomina un gruppo
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Rimpiazza i veicoli del {GROUP}
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Impossibile creare il gruppo...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Impossibile eliminare il gruppo...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Impossibile rinominare il gruppo...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Impossibile rimuovere tutti i veicoli del gruppo...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Impossibile aggiungere il veicolo al gruppo...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Impossibile aggiungere veicoli condivisi al gruppo...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Gruppi - Fare clic su un gruppo per elencare tutti i suoi veicoli
+STR_GROUP_CREATE_TIP                                            :{BLACK}Fare clic per creare un gruppo
+STR_GROUP_DELETE_TIP                                            :{BLACK}Elimina il gruppo selezionato
+STR_GROUP_RENAME_TIP                                            :{BLACK}Rinomina il gruppo selezionato
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Fare clic per proteggere questo gruppo dal rimpiazzo automatico
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Profitto quest'anno: {GREEN}{CURRENCY} {BLACK}(anno scorso: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Profitto quest'anno: {RED}{CURRENCY} {BLACK}(anno scorso: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Profitto quest'anno: {GREEN}{CURRENCY} {BLACK}(anno scorso: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Profitto quest'anno: {RED}{CURRENCY} {BLACK}(anno scorso: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/japanese.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/japanese.txt	Fri May 25 00:25:08 2007 +0000
@@ -3,6 +3,8 @@
 ##isocode ja_JP
 ##plural 1
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}地図の端を越えています
@@ -1046,6 +1048,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}新型グローバルパスファインダー(NPF):{ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}重い列車のシミュレーションのための重量乗数の設定:{ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}町有道路上に通過点の建設を許容:{ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}隣接した駅の建設を許容:{ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}常に小型空港の建設を許容:{ORANGE}{STRING}
 
@@ -1098,6 +1101,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :切
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}地図のスクロール速度:{ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}新規ゲームを開始したときに自動的にポーズ:{ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}詳細の車両リストを使用:{ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}一人のプレヤーの列車数上限:{ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}一人のプレヤーの道路車両数上限:{ORANGE}{STRING}
@@ -1132,6 +1136,13 @@
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}ドラッグするときの信号設備頻度:{ORANGE}{STRING}
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}次の年まで腕木式信号を建設:{ORANGE}{STRING}
 
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}シナリオエディタを使用時に、「道路網を拡大せず」という道路網が選択できません
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}道路網の選択:{ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :道路網を拡大せず
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :デフォルト
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :改善の道路網
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :格子状(2x2)
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :格子状(3x3)
 
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}主のツールバーの位置:{ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :左
@@ -1578,6 +1589,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :前位信号のある線路
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :後位信号のある線路
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :統合信号のある線路
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}先に駅を破壊しなければなりません
 
 
 
@@ -2005,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING}ヘリポート
 STR_SV_STNAME_FOREST                                            :{STRING}森林
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2143,8 +2157,8 @@
 STR_7039_VEHICLES                                               :{GOLD}車両数:
 STR_TRAINS                                                      :{WHITE}列車{COMMA}本
 STR_ROAD_VEHICLES                                               :{WHITE}道路車両{COMMA}両
-STR_AIRCRAFT                                                    :{WHITE}{COMMA}台の飛行機
-STR_SHIPS                                                       :{WHITE}{COMMA}隻の船舶
+STR_AIRCRAFT                                                    :{WHITE}飛行機{COMMA}台
+STR_SHIPS                                                       :{WHITE}船舶{COMMA}隻
 STR_7042_NONE                                                   :{WHITE}なし
 STR_7043_FACE_SELECTION                                         :{WHITE}顔の選択
 STR_7044_MALE                                                   :{BLACK}男性
@@ -2729,7 +2743,7 @@
 STR_9802_CAN_T_BUILD_DOCK_HERE                                  :{WHITE}ここに埠頭が建設できません...
 STR_9803_SHIP_DEPOT                                             :{WHITE}{TOWN}造船所
 STR_9804_NEW_SHIPS                                              :{BLACK}新規船舶
-STR_9805_SHIPS                                                  :{WHITE}{COMPANY} - {COMMA}隻の船舶
+STR_9805_SHIPS                                                  :{WHITE}{COMPANY} - 船舶{COMMA}隻
 STR_9808_NEW_SHIPS                                              :{WHITE}新規船舶
 STR_9809_BUILD_SHIP                                             :{BLACK}船舶を購入
 STR_CLONE_SHIP                                                  :{BLACK}船舶をクローン
@@ -2805,7 +2819,7 @@
 STR_A005_NEW_AIRCRAFT                                           :{WHITE}新規飛行機
 STR_A006_BUILD_AIRCRAFT                                         :{BLACK}飛行機を購入
 STR_A008_CAN_T_BUILD_AIRCRAFT                                   :{WHITE}飛行機が購入できません...
-STR_A009_AIRCRAFT                                               :{WHITE}{COMPANY} - {COMMA}台の飛行機
+STR_A009_AIRCRAFT                                               :{WHITE}{COMPANY} - 飛行機{COMMA}台
 STR_A00A                                                        :{WHITE}{VEHICLE}
 STR_A00B_ORDERS                                                 :{WHITE}{VEHICLE}(指令)
 STR_A00C_DETAILS                                                :{WHITE}{VEHICLE}(詳細)
@@ -3006,10 +3020,10 @@
 STR_DEPOT_AUTOREPLACE_SHIP_TIP                                  :{BLACK}造船所内のすべての船舶を自動的に交換します
 STR_DEPOT_AUTOREPLACE_AIRCRAFT_TIP                              :{BLACK}格納庫内のすべての飛行機を自動的に交換します
 
-STR_VEHICLE_LIST_TRAIN_DEPOT                                    :{BLACK}{STRING} - {COMMA}本の列車
-STR_VEHICLE_LIST_ROADVEH_DEPOT                                  :{BLACK}{STRING} - {COMMA}両の道路車両
-STR_VEHICLE_LIST_SHIP_DEPOT                                     :{BLACK}{STRING} - {COMMA}隻の船舶
-STR_VEHICLE_LIST_AIRCRAFT_DEPOT                                 :{BLACK}{STRING} - {COMMA}台の飛行機
+STR_VEHICLE_LIST_TRAIN_DEPOT                                    :{BLACK}{STRING} - 列車{COMMA}本
+STR_VEHICLE_LIST_ROADVEH_DEPOT                                  :{BLACK}{STRING} - 道路車両{COMMA}両
+STR_VEHICLE_LIST_SHIP_DEPOT                                     :{BLACK}{STRING} - 船舶{COMMA}隻
+STR_VEHICLE_LIST_AIRCRAFT_DEPOT                                 :{BLACK}{STRING} - 飛行機{COMMA}台
 
 STR_REPLACE_VEHICLES_WHITE                                      :{WHITE}{STRING}を交換
 STR_REPLACE_VEHICLES_START                                      :{BLACK}車両の交換を開始
@@ -3106,6 +3120,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}始める年を変えます
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}リサイズ警告
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}ソース地図をリサイズしすぎることはお勧めしません。地形作成を続けてもよろしいですか?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}道路網の警告
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}「道路網を拡大せず」という道路網をおすすめしません。続けてもよろしいですか?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}ハイトマップ名:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}サイズ:{ORANGE}{NUM} x {NUM}
@@ -3178,3 +3194,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}交通社所有の建物などの透明性を入/切
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}橋の透明性を入/切
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}灯台、送信機などの透明性を入/切
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :グループ {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :すべての列車
+STR_GROUP_ALL_ROADS                                             :すべての道路車両
+STR_GROUP_ALL_SHIPS                                             :すべての船舶
+STR_GROUP_ALL_AIRCRAFTS                                         :すべての飛行機
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :共有車両を追加
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :すべての車両を取り除く
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - 列車{COMMA}本
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - 道路車両{COMMA}両
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - 船舶{COMMA}隻
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - 飛行機{COMMA}台
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}グループ名を変更
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}"{GROUP}"内の車両を交換
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}グループが作成できません...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}グループが削除できません...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}グループ名が変更できません...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}グループ内のすべての車両が取り除けません...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}この車両がこのグループに追加できません...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}グループに共有車両が追加できません...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}グループ - グループをクリックしてグループ内のすべての車両のリストが表示します
+STR_GROUP_CREATE_TIP                                            :{BLACK}クリックしてグループを作成します
+STR_GROUP_DELETE_TIP                                            :{BLACK}選択したグループを削除します
+STR_GROUP_RENAME_TIP                                            :{BLACK}選択したグループの名称を変更します
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}このグループ内の車両を自動交換しません
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}今年の収益:{GREEN}{CURRENCY} {BLACK}(昨年:{GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}今年の収益:{RED}{CURRENCY} {BLACK}(昨年:{GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}今年の収益:{GREEN}{CURRENCY} {BLACK}(昨年:{RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}今年の収益:{RED}{CURRENCY} {BLACK}(昨年:{RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/korean.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/korean.txt	Fri May 25 00:25:08 2007 +0000
@@ -1099,6 +1099,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :끄기
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}맵 스크롤 속도: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}새로운 게임 시작할 때 자동으로 일시정지: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}진보된 차량 목록 사용: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}최대 열차 수: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}최대 자동차 수: {ORANGE}{STRING}
@@ -2013,6 +2014,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} 헬리포트
 STR_SV_STNAME_FOREST                                            :{STRING} 삼림
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3188,3 +3191,38 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}정거장, 차량기지, 웨이포인트, 연결고리와 같은 건설 가능한 것들에 대한 투명 전환
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}다리 투명 전환
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}등대와 안테나와 같은 구조물 투명 전환
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :그룹 {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :모든 기차
+STR_GROUP_ALL_ROADS                                             :모든 차량
+STR_GROUP_ALL_SHIPS                                             :모든 선박
+STR_GROUP_ALL_AIRCRAFTS                                         :모든 항공기
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :모든 공유된 차량
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :모든 차량 제거
+
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} 항공기
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}그룹 이름 바꾸기
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}"{GROUP}"의 차량 교체
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}그룹을 만들 수 없습니다...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}이 그룹을 지울 수 없습니다.
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}그룹의 이름을 바꿀 수 없습니다.
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}이 구릅의 모든 차량을 제거할 수 없습니다.
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}이 그룹에 차량을 추가할 수 없습니다.
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}이 구릅에 공유된 차량을 추가할 수 없습니다.
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}그룹 - 땅을 클릭하면 이 그룹의 모든 차량을 나열
+STR_GROUP_CREATE_TIP                                            :{BLACK}그룹 만들기
+STR_GROUP_DELETE_TIP                                            :{BLACK}선택한 그룹 삭제
+STR_GROUP_RENAME_TIP                                            :{BLACK}선택한 그룹 이름 바꾸기
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}전체 자동 교체로부터 이 그룹 보호
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}올해의 수입: {GREEN}{CURRENCY} {BLACK}(작년: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}올해의 수입: {RED}{CURRENCY} {BLACK}(작년: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}올해 수입: {GREEN}{CURRENCY} {BLACK}(작년: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}올해 수입: {RED}{CURRENCY} {BLACK}(작년: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/russian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/russian.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case m f n p
 ##gender m f n p
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Край карты
@@ -1100,6 +1102,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :не использовать
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Скорость смещения обзора прокруткой колеса мыши: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Автопауза в начале игры: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Использовать расширенный список транспорта: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Максимальное количество поездов на игрока: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Максимальное количество автотранспорта на игрока: {ORANGE}{STRING}
@@ -1133,6 +1136,15 @@
 STR_CONFIG_PATCHES_ALLOW_SHARES                                 :{LTBLUE}Разрешить торговлю акциями других компаний
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}При установке светофоров линией, ставить кажд{P 1 ую ые ые}: {ORANGE}{STRING} клет{P 1 ку ки ок}
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Строить семафоры старого стиля: {ORANGE}до {STRING} года
+
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Расположение дорог "не строить дороги" не действительно в редакторе сценариев
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Расположение дорог у городов: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :не строить дороги
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :старый алгоритм
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :улучшенный алгоритм
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :решёткой 2x2
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :решёткой 3x3
+
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Положение главной панели инструментов: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :слева
 STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER                           :в центре
@@ -2005,6 +2017,8 @@
 STR_SV_STNAME_HELIPORT                                          :Площадка {STRING}
 STR_SV_STNAME_FOREST                                            :Лес {STRING}
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2044,6 +2058,7 @@
 ############ range for difficulty settings ends
 
 STR_26816_NONE                                                  :Нет
+STR_NUM_VERY_LOW                                                :Очень низкое
 STR_6816_LOW                                                    :Низкое
 STR_6817_NORMAL                                                 :Среднее
 STR_6818_HIGH                                                   :Большое
@@ -3116,6 +3131,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Изменить год начала игры
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Выход за пределы доступных значений
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Увеличение карты до таких размеров не рекомендуется. Продолжить?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Предупреждение о расположении дорог
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}Расположение дорог "не строить дороги" не рекомендуется. Продолжить создание карты?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Имя РЕЛЬЕФА:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Размер: {ORANGE}{NUM} x {NUM}
@@ -3188,3 +3205,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Переключить прозрачность зданий, которые можно строить игроком. Например -- станции, депо, точки пути и столбы для электричества.
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Переключить прозрачность мостов
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Переключить прозрачность зданий, вроде антенн и маяков.
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Группа {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Все поезда
+STR_GROUP_ALL_ROADS                                             :Весь автотранспорт
+STR_GROUP_ALL_SHIPS                                             :Все корабли
+STR_GROUP_ALL_AIRCRAFTS                                         :Все самолёты
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Добавить с общими заданиями
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Удалить всех
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} поезд{P "" а ов}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} автомашин{P а ы ""}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} корабл{P ь я ей}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} самолёт{P "" а ов}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Переименовать группу
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Заменить транспорт в группе "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Не могу создать группу...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Не могу удалить группу...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Не могу переименовать группу...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Не могу удалить весь транспорт с группы...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Не могу добавить транспорт в группу...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Не могу добавить транспорт с общими заданиями в группу...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Группы - Щёлкните группу для отображения в списке
+STR_GROUP_CREATE_TIP                                            :{BLACK}Создать группу
+STR_GROUP_DELETE_TIP                                            :{BLACK}Удалить выбранную группу
+STR_GROUP_RENAME_TIP                                            :{BLACK}Переименовать выбранную группу
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}В зажатом состоянии защищает группу от всеобщей автозамены
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Прибыль этот год: {GREEN}{CURRENCY} {BLACK}(прошлый год: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Прибыль этот год: {RED}{CURRENCY} {BLACK}(прошлый год: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Прибыль за год: {GREEN}{CURRENCY} {BLACK}(прошлый год: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Прибыль за год: {RED}{CURRENCY} {BLACK}(прошлый год: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/slovak.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/slovak.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case g
 ##gender m z s
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Za okrajom mapy
@@ -1110,6 +1112,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Novy globalny algoritmus hladania cesty (NPF namiesto NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Váhový násobok pre nákladné vlaky: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Povolit prejazdné zastávky na mestských cestách: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Povolit stavbu oddelených staníc: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Vzdy povolit stavbu malych letisk: {ORANGE}{STRING}
 
@@ -1162,6 +1165,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Vypnuté
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Rychlost posúvania mapy: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automaticka pauza pri štarte novej hry: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Použit vylepšený zoznam vozidiel: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Maximalny pocet vlakov hraca: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Maximalny pocet automobilov hraca: {ORANGE}{STRING}
@@ -1195,6 +1199,15 @@
 STR_CONFIG_PATCHES_ALLOW_SHARES                                 :{LTBLUE}Povolit nakup akcii ostatnych spolocnosti
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}Pri stavbe tahanim umiestnit semafory na kazde: {ORANGE}{STRING}. pole
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Automatická stavba semafórov pred: {ORANGE}{STRING}
+
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Struktúra mesta "žiadne cesty naviac" nie je platná v editore scenárov
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Štruktúra mestských ciestt: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :žiadne cesty naviac
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :štandardná
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :lepšie cesty
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :mriežka 2x2
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :mriežka 3x3
+
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Pozicia hlavneho menu: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Nalavo
 STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER                           :V strede
@@ -1640,6 +1653,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Zeleznicne kolaje s pre-signalmi
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Zeleznicne kolaje s exit-signalmi
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Zeleznicne kolaje s combo-signalmi
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Je potrebné najprv odstránit železnicnú stanicu
 
 
 
@@ -2067,6 +2081,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Heliport
 STR_SV_STNAME_FOREST                                            :{STRING} Les
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2102,6 +2118,7 @@
 ############ range for difficulty settings ends
 
 STR_26816_NONE                                                  :Ziadny
+STR_NUM_VERY_LOW                                                :Velmi malý
 STR_6816_LOW                                                    :Nizke
 STR_6817_NORMAL                                                 :Normalne
 STR_6818_HIGH                                                   :Vysoke
@@ -3167,6 +3184,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Zmenit rok zaciatku hry
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Upozornenie na stupnicu
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Prilis velka zmena velkosti zdrojovej mapy sa neodporuca. Pokracovat s generovanim?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Upozornenie na štruktúra mesta
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}Štruktúra mesta  "žiadne cesty naviac" sa neodporúca. Pokracovat s generovaním?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Nazov vyskovej mapy:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Velkost: {ORANGE}{NUM} x {NUM}
@@ -3239,3 +3258,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Prepnút priehladnost staníc, garáží, tratí, ...
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Prepnút priehladnost mostov
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Prepnút priehladnost objektov ako sú majáky a antény
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Skupina {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Všetky vlaky
+STR_GROUP_ALL_ROADS                                             :Všetky cestné vozidlá
+STR_GROUP_ALL_SHIPS                                             :Všetky lode
+STR_GROUP_ALL_AIRCRAFTS                                         :Všetky lietadlá
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Pridat zdielané vozidlá
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Odstránit všetky vozidlá
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Vlak{P "" y ov}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Vozid{P lo lá ied}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Lod{P "" e í}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Lietad{P lo lá iel}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Premenovat skupinu
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Nahradit vozidlá skupiny "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Nie je možné vytvorit skupinu ...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Nie je možné zrušit túto skupinu ...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Nie je možné premenovat skupinu ...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Nie je možné odstránit všetky vozdilá z tejto skupiny ...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Nie je možné pridat vozidlo do tejto skupiny
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Nie je možné pridat zdielané vozidlo do skupiny
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Skupiny  - kliknite na skupinu pre zobrazenie všetkých vozidiel skupiny
+STR_GROUP_CREATE_TIP                                            :{BLACK}Kliknite pre vytvorenie skupiny
+STR_GROUP_DELETE_TIP                                            :{BLACK}Zrušit vybranú skupinu
+STR_GROUP_RENAME_TIP                                            :{BLACK}Premenovat vybranú skupinu
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Kliknite pre znemoznenie automatického nahradzovania v skupine
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Zisk tento rok: {GREEN}{CURRENCY} {BLACK}(minulý rok: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Zisk tento rok: {RED}{CURRENCY} {BLACK}(lminulý rok: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Zisk tento rok: {GREEN}{CURRENCY} {BLACK}(minulý rok: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Zisk tento rok: {RED}{CURRENCY} {BLACK}(minulý rok: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/slovenian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/slovenian.txt	Fri May 25 00:25:08 2007 +0000
@@ -1173,6 +1173,15 @@
 STR_CONFIG_PATCHES_ALLOW_SHARES                                 :{LTBLUE}Dovoli kupovanje delnic od drugih podjetij
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}Med vlečenjem postavi signale vsakih: {ORANGE}{STRING} ploščic
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Samodejno postavi semaforje pred: {ORANGE}{STRING}
+
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Mestna razporeditev "nič več cest" ni veljavna v urejevalniku terena
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Izberi razporeditev mestnih cest: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :nič več cest
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :privzeto
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :boljše ceste
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2x2 mreža
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3x3 mreža
+
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Pozicija glavne orodne vrstice: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Levo
 STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER                           :Sredina
@@ -2083,6 +2092,7 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Pristajališče
 STR_SV_STNAME_FOREST                                            :{STRING} Gozd
 
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -2118,6 +2128,7 @@
 ############ range for difficulty settings ends
 
 STR_26816_NONE                                                  :Brez
+STR_NUM_VERY_LOW                                                :Zelo malo
 STR_6816_LOW                                                    :Malo
 STR_6817_NORMAL                                                 :Normalno
 STR_6818_HIGH                                                   :Veliko
@@ -3183,6 +3194,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Spremeni začetno leto
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Opozorilo za merilo
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Prevelika sprememba velikosti ozemlja ni priporočena. Nadaljujem?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Opozorilo mestne  razporeditve
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}Mestna razporeditev "nič več cest" ni priporočena. Nadaljuješ z ustvarjanjem?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Ime višinskega zemljevida:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Velikost: {ORANGE}{NUM} x {NUM}
@@ -3255,3 +3268,11 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Prozoren ali navaden pogled ostalih objektov kot so postaje, garaže...
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Prozoren ali navaden pogled mostov
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Prozoren ali navaden pogled struktur kot so antene, svetilniki...
+
+##### Mass Order
+
+
+
+
+
+########
--- a/src/lang/spanish.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/spanish.txt	Fri May 25 00:25:08 2007 +0000
@@ -1099,6 +1099,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Nada
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Velocidad del scroll sobre el mapa: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automaticamente hace pausa cuando empieza un juego nuevo: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Usar la lista avanza de vehículos: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Máx trenes por jugador: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Máx vehículos de carretera por jugador: {ORANGE}{STRING}
@@ -1133,6 +1134,13 @@
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}Cuando arrastre colocar señales cada: {ORANGE}{STRING} casilla(s)
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Coloca automáticamente semáforos antes de: {ORANGE}{STRING}
 
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}El trazado de ciudad "no más carreteras" no es válido en el editor de escenarios
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Selecciona trazado de carretera en ciudad: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :no más carreteras
+STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :por defecto
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :mejores carreteras
+STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :rejilla 2x2
+STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :rejilla 3x3
 
 STR_CONFIG_PATCHES_TOOLBAR_POS                                  :{LTBLUE}Posición de la barra de herramientas principal: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT                             :Izquierda
@@ -2006,6 +2014,7 @@
 STR_SV_STNAME_HELIPORT                                          :Helipuerto de {STRING}
 STR_SV_STNAME_FOREST                                            :Bosque de {STRING}
 
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3107,6 +3116,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}Cambiar año de inicio
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}Alerta de escala
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}Cambiar demasiado el tamaño del mapa de origen no está recomendado. ¿Desea continuar con la generación?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}Aviso de trazado de ciudad
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW}El trazado de ciudad "no más carreteras" no es recomendable. ¿Continuar con la generación?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}Nombre del mapa de alturas:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}Tamaño: {ORANGE}{NUM} x {NUM}
@@ -3179,3 +3190,35 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Activar transparencias para construcciones como estaciones, depósitos, puntos de paso, etc.
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Activar transparencias para puentes
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Activar transparencias para estructuras como faros, antenas, etc.
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Grupo {COMMA}
+STR_GROUP_ALL_TRAINS                                            :Todos los trenes
+STR_GROUP_ALL_ROADS                                             :Todos los vehículos de carretera
+STR_GROUP_ALL_SHIPS                                             :Todos los barcos
+STR_GROUP_ALL_AIRCRAFTS                                         :Todas las aeronaves
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Todos los vehículos compartidos
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Quitar todos los vehículos
+
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Renombrar un grupo
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}No se puede crear grupo...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}No se puede borrar este grupo...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}No se puede renombrar grupo...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}No se pueden quitar todos los vehículos de este grupo...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}No se puede añadir el vehículo a este grupo...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}No se pueden añadir vehículos compartidos al grupo...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Grupos - Pulsa en el grupo para ver la lista de vehículos que tiene el grupo
+STR_GROUP_CREATE_TIP                                            :{BLACK}Pulsa para crear un grupo
+STR_GROUP_DELETE_TIP                                            :{BLACK}Borrar el grupo seleccionado
+STR_GROUP_RENAME_TIP                                            :{BLACK}Renombrar el grupo seleccionado
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Pulsa para proteger este grupo del auto reemplazado global
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Beneficio este año: {GREEN}{CURRENCY} {BLACK}(año pasado: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Beneficio este año: {RED}{CURRENCY} {BLACK}(año pasado: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Beneficio este año: {GREEN}{CURRENCY} {BLACK}(año pasado: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Beneficio este año: {RED}{CURRENCY} {BLACK}(año pasado: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/swedish.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/swedish.txt	Fri May 25 00:25:08 2007 +0000
@@ -1098,6 +1098,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Avstängd
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Mushjulshastighet: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Pausa automatiskt vid start av nytt spel: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Använd den avancerade fordonslistan: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Max antal tåg per spelare: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Max antal vägfordon per spelare: {ORANGE}{STRING}
@@ -2012,6 +2013,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Helikopterplats
 STR_SV_STNAME_FOREST                                            :{STRING} Skog
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3187,3 +3190,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Växla genomskinlighet för byggnader såsom stationer, depåer, riktmärken eller kedjelinje
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Växla genomskinlighet för industrier
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Växla genomskinlighet för byggnader såsom fyrar och antenner, kanske i framtiden även ögongodis
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Grupp {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Alla tåg
+STR_GROUP_ALL_ROADS                                             :Alla vägfordon
+STR_GROUP_ALL_SHIPS                                             :Alla skepp
+STR_GROUP_ALL_AIRCRAFTS                                         :Alla flygplan
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Lägg till delade fordon
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Ta bort alla fordon
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Tåg{P "" s}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Vägfordon{P "" s}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Skepp{P "" s}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Flygplan
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Döp om en grupp
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Byt ut fordonen i "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Kan inte skapa grupp...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Kan inte ta bort denna grupp...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Kan inte döpa om grupp...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Kan inte ta bort alla fordon från denna grupp...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Kan inte lägga till fordonet till denna grupp...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Kan inte lägga till delade fordon till grupp...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Grupper - Klicka på en grupp för att lista alla fordon i denna grupp
+STR_GROUP_CREATE_TIP                                            :{BLACK}Klicka för att skapa en grupp
+STR_GROUP_DELETE_TIP                                            :{BLACK}Ta bort den valda gruppen
+STR_GROUP_RENAME_TIP                                            :{BLACK}Döp om den valda gruppen
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Klicka för att skydda denna grupp från globalt autoutbyte
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Vinst detta år: {GREEN}{CURRENCY} {BLACK}(förra året: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Vinst detta år: {RED}{CURRENCY} {BLACK}(förra året: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Vinst detta år: {GREEN}{CURRENCY} {BLACK}(förra året: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Vinst detta år: {RED}{CURRENCY} {BLACK}(förra året: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/lang/traditional_chinese.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/traditional_chinese.txt	Fri May 25 00:25:08 2007 +0000
@@ -25,7 +25,7 @@
 STR_0012_OIL                                                    :石油
 STR_0013_LIVESTOCK                                              :牲畜
 STR_0014_GOODS                                                  :商品
-STR_0015_GRAIN                                                  :穀粒
+STR_0015_GRAIN                                                  :穀物
 STR_0016_WOOD                                                   :木材
 STR_0017_IRON_ORE                                               :鐵礦石
 STR_0018_STEEL                                                  :鋼鐵
@@ -57,7 +57,7 @@
 STR_0032_OIL                                                    :石油
 STR_0033_LIVESTOCK                                              :牲畜
 STR_0034_GOODS                                                  :商品
-STR_0035_GRAIN                                                  :穀粒
+STR_0035_GRAIN                                                  :穀物
 STR_0036_WOOD                                                   :木材
 STR_0037_IRON_ORE                                               :鐵礦石
 STR_0038_STEEL                                                  :鋼鐵
@@ -89,7 +89,7 @@
 STR_QUANTITY_OIL                                                :{VOLUME}石油
 STR_QUANTITY_LIVESTOCK                                          :{COMMA}頭牲畜
 STR_QUANTITY_GOODS                                              :{COMMA}箱商品
-STR_QUANTITY_GRAIN                                              :{WEIGHT}小麥
+STR_QUANTITY_GRAIN                                              :{WEIGHT}穀物
 STR_QUANTITY_WOOD                                               :{WEIGHT}木材
 STR_QUANTITY_IRON_ORE                                           :{WEIGHT}鐵礦
 STR_QUANTITY_STEEL                                              :{WEIGHT}鋼鐵
@@ -101,7 +101,7 @@
 STR_QUANTITY_FOOD                                               :{WEIGHT}食物
 STR_QUANTITY_PAPER                                              :{WEIGHT}紙張
 STR_QUANTITY_GOLD                                               :{COMMA}包黃金
-STR_QUANTITY_WATER                                              :{VOLUME}食水
+STR_QUANTITY_WATER                                              :{VOLUME}淡水
 STR_QUANTITY_WHEAT                                              :{WEIGHT}小麥
 STR_QUANTITY_RUBBER                                             :{VOLUME}橡膠
 STR_QUANTITY_SUGAR                                              :{WEIGHT}砂糖
@@ -1132,11 +1132,11 @@
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}拖放時訊號燈之間距離:{ORANGE}{STRING} 格
 STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}於日期前自動建立舊式號誌臂:{ORANGE}{STRING}年
 
-STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}在場景編輯器中,"市鎮道路不再配置" 是不合法的
-STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}選擇市鎮道路配置:{ORANGE}{STRING}
-STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :道路不再配置
+STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}在場景編輯器中,"市鎮道路不再規劃" 是不可行的
+STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}選擇市鎮道路規劃:{ORANGE}{STRING}
+STR_CONFIG_PATCHES_TOWN_LAYOUT_NO_ROADS                         :道路不再規劃
 STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT                          :預設
-STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :較好的配置
+STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS                     :較好的規劃
 STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID                         :2乘2網格
 STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID                         :3乘3網格
 
@@ -1739,7 +1739,7 @@
 
 ##id 0x3000
 STR_3000_RAIL_STATION_SELECTION                                 :{WHITE}選擇鐵道車站
-STR_3001_AIRPORT_SELECTION                                      :{WHITE}選擇飛機場
+STR_3001_AIRPORT_SELECTION                                      :{WHITE}選擇機場
 STR_3002_ORIENTATION                                            :{BLACK}方向
 STR_3003_NUMBER_OF_TRACKS                                       :{BLACK}軌數
 STR_3004_PLATFORM_LENGTH                                        :{BLACK}月台長度
@@ -1753,7 +1753,7 @@
 STR_300A_0                                                      :{WHITE}{STATION} {STATIONFEATURES}
 STR_300B_MUST_DEMOLISH_RAILROAD                                 :{WHITE}必須先摧毀鐵道車站
 STR_300D_TOO_CLOSE_TO_ANOTHER_AIRPORT                           :{WHITE}太靠近另一個飛機場
-STR_300E_MUST_DEMOLISH_AIRPORT_FIRST                            :{WHITE}必須先摧毀飛機場
+STR_300E_MUST_DEMOLISH_AIRPORT_FIRST                            :{WHITE}必須先剷除機場
 
 STR_3030_RENAME_STATION_LOADING                                 :修改車站/載貨區名稱
 STR_3031_CAN_T_RENAME_STATION                                   :{WHITE}不能修改車站名稱...
@@ -1802,7 +1802,7 @@
 STR_STATION_SIGN_TINY                                           :{TINYFONT}{STATION}
 STR_305E_RAILROAD_STATION                                       :鐵道車站
 STR_305F_AIRCRAFT_HANGAR                                        :飛機棚
-STR_3060_AIRPORT                                                :飛機場
+STR_3060_AIRPORT                                                :機場
 STR_3061_TRUCK_LOADING_AREA                                     :貨運場
 STR_3062_BUS_STATION                                            :公車站
 STR_3063_SHIP_DOCK                                              :船塢
@@ -2803,7 +2803,7 @@
 
 ##id 0xA000
 STR_A000_AIRPORTS                                               :{WHITE}機場
-STR_A001_CAN_T_BUILD_AIRPORT_HERE                               :{WHITE}無法在此建造機場...
+STR_A001_CAN_T_BUILD_AIRPORT_HERE                               :{WHITE}無法在此興建機場...
 STR_A002_AIRCRAFT_HANGAR                                        :{WHITE}{STATION} 停機棚
 STR_A003_NEW_AIRCRAFT                                           :{BLACK}購買飛機
 STR_CLONE_AIRCRAFT                                              :{BLACK}複製飛機
@@ -2834,12 +2834,12 @@
 STR_A01A_CAPACITY                                               :{BLACK}容量:{LTBLUE}{CARGO}
 STR_A01B_AIRCRAFT_MUST_BE_STOPPED                               :{WHITE}飛機必須停在機棚内
 STR_A01C_CAN_T_SELL_AIRCRAFT                                    :{WHITE}無法出售飛機...
-STR_A01D_AIRPORT_CONSTRUCTION                                   :建造機場
-STR_A01E_BUILD_AIRPORT                                          :{BLACK}建造機場
+STR_A01D_AIRPORT_CONSTRUCTION                                   :興建機場
+STR_A01E_BUILD_AIRPORT                                          :{BLACK}興建機場
 STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT                             :{BLACK}飛機 - 點選飛機顯示詳細資料
 STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES                            :{BLACK}購買新飛機 (需要有機棚的機場)
 STR_A021_AIRCRAFT_CLICK_ON_AIRCRAFT                             :{BLACK}飛機 - 點選飛機顯示詳細資料
-STR_A022_BUILD_NEW_AIRCRAFT                                     :{BLACK}建造新機場
+STR_A022_BUILD_NEW_AIRCRAFT                                     :{BLACK}購買新飛機
 STR_A023_DRAG_AIRCRAFT_TO_HERE_TO                               :{BLACK}將飛機拉至此即可出售
 STR_A024_CENTER_MAIN_VIEW_ON_HANGAR                             :{BLACK}將主視野帶到機棚位置
 STR_A025_AIRCRAFT_SELECTION_LIST                                :{BLACK}飛機清單 - 點選飛機檢視詳細資料
@@ -2855,7 +2855,7 @@
 STR_A031_CAN_T_NAME_AIRCRAFT                                    :{WHITE}無法命名飛機
 STR_A032_NAME_AIRCRAFT                                          :{BLACK}命名飛機
 STR_A033_CITIZENS_CELEBRATE_FIRST                               :{BLACK}{BIGFONT}市民慶賀 . . .{}首架飛機抵達 {STATION}!
-STR_A034_PLANE_CRASH_DIE_IN_FIREBALL                            :{BLACK}{BIGFONT}飛機墜毀!{}{COMMA} 名死於 {STATION} 機場的火球下
+STR_A034_PLANE_CRASH_DIE_IN_FIREBALL                            :{BLACK}{BIGFONT}墜機!{}{COMMA} 名乘客與機組員死於 {STATION} 的火球下
 STR_PLANE_CRASH_OUT_OF_FUEL                                     :{BLACK}{BIGFONT}飛機墜毀!{}飛機用光燃油, {COMMA} 死在火球裡!
 STR_A036                                                        :{TINYFONT}{BLACK}{STATION}
 STR_A037_RENAME                                                 :{BLACK}更名
@@ -3085,7 +3085,7 @@
 STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT                          :{BLACK}動力車廂:{GOLD}+{POWER}{BLACK} 重量:{GOLD}+{WEIGHT_S}
 STR_PURCHASE_INFO_REFITTABLE_TO                                 :{BLACK}可改裝成:{GOLD}
 STR_PURCHASE_INFO_ALL_TYPES                                     :所有酬載類型
-STR_PURCHASE_INFO_ALL_BUT                                       :{GOLD} 以外皆可
+STR_PURCHASE_INFO_ALL_BUT                                       :{GOLD}除了
 STR_PURCHASE_INFO_MAX_TE                                        :{BLACK}最大牽引力:{GOLD}{FORCE}
 
 ########### String for New Landscape Generator
@@ -3113,8 +3113,8 @@
 STR_START_DATE_QUERY_CAPT                                       :{WHITE}變更開始年份
 STR_HEIGHTMAP_SCALE_WARNING_CAPTION                             :{WHITE}縮放警告
 STR_HEIGHTMAP_SCALE_WARNING_MESSAGE                             :{YELLOW}不建議過度縮放地圖。繼續產生?
-STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}市鎮配置警告
-STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW} "市鎮道路不再配置" 是不建議的。要繼續產生嗎?
+STR_TOWN_LAYOUT_WARNING_CAPTION                                 :{WHITE}市鎮規劃警告
+STR_TOWN_LAYOUT_WARNING_MESSAGE                                 :{YELLOW} "市鎮道路不再規劃" 是不建議的。要繼續產生嗎?
 STR_SNOW_LINE_HEIGHT_NUM                                        :{NUM}
 STR_HEIGHTMAP_NAME                                              :{BLACK}高度圖名稱:
 STR_HEIGHTMAP_SIZE                                              :{BLACK}大小:{ORANGE}{NUM} x {NUM}
@@ -3156,8 +3156,8 @@
 STR_HELIDEPOT                                                   :{BLACK}直升機棚
 STR_HELISTATION                                                 :{BLACK}直升機站
 
-STR_SMALL_AIRPORTS                                              :{BLACK}小機場
-STR_LARGE_AIRPORTS                                              :{BLACK}大機場
+STR_SMALL_AIRPORTS                                              :{BLACK}小型機場
+STR_LARGE_AIRPORTS                                              :{BLACK}大型機場
 STR_HUB_AIRPORTS                                                :{BLACK}轉運機場
 STR_HELIPORTS                                                   :{BLACK}直升機場
 
--- a/src/lang/turkish.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/turkish.txt	Fri May 25 00:25:08 2007 +0000
@@ -3,6 +3,8 @@
 ##isocode tr_TR
 ##plural 1
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}Harita kenarında
@@ -2008,6 +2010,7 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} Heliport
 STR_SV_STNAME_FOREST                                            :{STRING} Ormanı
 
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3179,3 +3182,36 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}İstasyonlar, garajlar tershaneler vb. için şeffaflık
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Köprüler için şeffaflık
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Antenler ve deniz fenerleri için şeffaflık
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Grup {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Bütün trenler
+STR_GROUP_ALL_ROADS                                             :Bütün arabalar
+STR_GROUP_ALL_SHIPS                                             :Bütün Gemiler
+STR_GROUP_ALL_AIRCRAFTS                                         :Bütün uçaklar
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Bütün paylaşılan araçlar
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Bütün araçları çıkar
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} Tren
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} Araba
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} Gemi
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} Uçak
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Grubun ismini değiştir
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}"{GROUP}"  Araçlarını Değiştir
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Grup oluşturulamıyor...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Bu grup silinemiyor...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Grubun ismi değiştirilemiyor...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Bu gruptaki bütün araçlar çıkartılamıyor...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Araç bu gruba eklenemiyor...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Paylaşılan araçlar bu gruba eklenemiyor...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Gruplar - Gruba ait araçları listelemek için grubun üzerine tıklayın
+STR_GROUP_CREATE_TIP                                            :{BLACK}Grup oluşturmak için tıklayın
+STR_GROUP_DELETE_TIP                                            :{BLACK}Seçili grubu sil
+STR_GROUP_RENAME_TIP                                            :{BLACK}Seçili grubun ismini değiştir
+
+
+########
--- a/src/lang/ukrainian.txt	Fri May 11 15:13:08 2007 +0000
+++ b/src/lang/ukrainian.txt	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 ##case r d z
 ##gender m f s mn
 
+#
+
 ##id 0x0000
 STR_NULL                                                        :
 STR_0001_OFF_EDGE_OF_MAP                                        :{WHITE}За межами карти
@@ -1172,6 +1174,7 @@
 STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL                          :{LTBLUE}Новий глобальний пошук шляху(NPF, замість NTP): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_FREIGHT_TRAINS                               :{LTBLUE}Множник ваги для імітації важких потягів: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Дозволити безпересадкові зупинки на муніципальних дорогах: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Дозволити будувати суміжні станції: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Будувати малі аеропорти можна завжди: {ORANGE}{STRING}
 
@@ -1224,6 +1227,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Відкл.
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Швидкість прокрутки колесом миші: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Автоматично ставити паузу при старті нової гри: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Використовувати покращений список транспорту: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Макс. поїздів у гравця: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_MAX_ROADVEH                                  :{LTBLUE}Макс. авто у гравця: {ORANGE}{STRING}
@@ -1711,6 +1715,7 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Колія з вхідними сигналами
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Колія з вихідними сигналами
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Колія з комбінованими сигналами
+STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Спочатку потрібно знести залізничну станцію
 
 
 
@@ -2175,6 +2180,8 @@
 STR_SV_STNAME_HELIPORT                                          :{STRING} ГелМайданчик
 STR_SV_STNAME_FOREST                                            :{STRING} Ліс
 
+STR_SV_GROUP_NAME                                               :{GROUP}
+
 ############ end of savegame specific region!
 
 ##id 0x6800
@@ -3350,3 +3357,41 @@
 STR_TRANSPARENT_BUILDINGS_DESC                                  :{BLACK}Переключити прозорість для споруд, таких як станції, депо, ЛЕП тощо
 STR_TRANSPARENT_BRIDGES_DESC                                    :{BLACK}Переключити прозорість для мостів
 STR_TRANSPARENT_STRUCTURES_DESC                                 :{BLACK}Переключити прозорість для споруд, таких як маяки та антенни (може, потім)
+
+##### Mass Order
+STR_GROUP_NAME_FORMAT                                           :Група {COMMA}
+STR_GROUP_TINY_NAME                                             :{TINYFONT}{GROUP}
+STR_GROUP_ALL_TRAINS                                            :Усі поїзди
+STR_GROUP_ALL_ROADS                                             :Усі авто
+STR_GROUP_ALL_SHIPS                                             :Усі кораблі
+STR_GROUP_ALL_AIRCRAFTS                                         :Усі літаки
+STR_GROUP_TINY_NUM                                              :{TINYFONT}{COMMA}
+STR_GROUP_ADD_SHARED_VEHICLE                                    :Добавити спільний транспорт
+STR_GROUP_REMOVE_ALL_VEHICLES                                   :Позбутися всього транспорту
+
+STR_GROUP_TRAINS_CAPTION                                        :{WHITE}{GROUP} - {COMMA} поїзд{P "" и ів}
+STR_GROUP_ROADVEH_CAPTION                                       :{WHITE}{GROUP} - {COMMA} автомобіл{P ь і ів}
+STR_GROUP_SHIPS_CAPTION                                         :{WHITE}{GROUP} - {COMMA} кораб{P ель лі лів}
+STR_GROUP_AIRCRAFTS_CAPTION                                     :{WHITE}{GROUP} - {COMMA} літак{P "" и ів}
+STR_GROUP_RENAME_CAPTION                                        :{BLACK}Перейменувати групу
+STR_GROUP_REPLACE_CAPTION                                       :{WHITE}Замінити транспорт групи "{GROUP}"
+
+STR_GROUP_CAN_T_CREATE                                          :{WHITE}Не можна створити групу...
+STR_GROUP_CAN_T_DELETE                                          :{WHITE}Не можна стерти групу...
+STR_GROUP_CAN_T_RENAME                                          :{WHITE}Не можна перейменувати групу...
+STR_GROUP_CAN_T_REMOVE_ALL_VEHICLES                             :{WHITE}Не можна позбутися всього транспорту цієї групи...
+STR_GROUP_CAN_T_ADD_VEHICLE                                     :{WHITE}Не можна додати цей транспорт у групу...
+STR_GROUP_CAN_T_ADD_SHARED_VEHICLE                              :{WHITE}Не можна додати спільний транспорт у групу...
+
+STR_GROUPS_CLICK_ON_GROUP_FOR_TIP                               :{BLACK}Групи - клікніть на групі, щоб побачити список транспорту цієї групи
+STR_GROUP_CREATE_TIP                                            :{BLACK}Клікніть, щоб створити групу
+STR_GROUP_DELETE_TIP                                            :{BLACK}Стерти вибрану групу
+STR_GROUP_RENAME_TIP                                            :{BLACK}Перейменувати вибрану групу
+STR_GROUP_REPLACE_PROTECTION_TIP                                :{BLACK}Клікніть, щоб захистити групу від глобальної автозаміни
+
+STR_PROFIT_GOOD_THIS_YEAR_GOOD_LAST_YEAR                        :{TINYFONT}{BLACK}Прибуток цього року: {GREEN}{CURRENCY} {BLACK}(торік: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_GOOD_LAST_YEAR                         :{TINYFONT}{BLACK}Прибуток цього року: {RED}{CURRENCY} {BLACK}(торік: {GREEN}{CURRENCY}{BLACK})
+STR_PROFIT_GOOD_THIS_YEAR_BAD_LAST_YEAR                         :{TINYFONT}{BLACK}Прибуток цього року: {GREEN}{CURRENCY} {BLACK}(торік: {RED}{CURRENCY}{BLACK})
+STR_PROFIT_BAD_THIS_YEAR_BAD_LAST_YEAR                          :{TINYFONT}{BLACK}Прибуток цього року: {RED}{CURRENCY} {BLACK}(торік: {RED}{CURRENCY}{BLACK})
+
+########
--- a/src/main_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/main_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -51,6 +51,7 @@
 
 static byte _terraform_size = 1;
 RailType _last_built_railtype;
+RoadType _last_built_roadtype;
 static int _scengen_town_size = 1; // depress medium-sized towns per default
 
 extern void GenerateIndustries();
@@ -310,7 +311,8 @@
 
 static void MenuClickBuildRoad(int index)
 {
-	ShowBuildRoadToolbar();
+	_last_built_roadtype = (RoadType)index;
+	ShowBuildRoadToolbar(_last_built_roadtype);
 }
 
 static void MenuClickBuildWater(int index)
@@ -880,8 +882,8 @@
 
 	switch (how) {
 		case ZOOM_IN:
-			if (vp->zoom == 0) return false;
-			vp->zoom--;
+			if (vp->zoom == ZOOM_LVL_MIN) return false;
+			vp->zoom = (ZoomLevel)((byte)vp->zoom - 1);
 			vp->virtual_width >>= 1;
 			vp->virtual_height >>= 1;
 
@@ -889,8 +891,8 @@
 			WP(w,vp_d).scrollpos_y += vp->virtual_height >> 1;
 			break;
 		case ZOOM_OUT:
-			if (vp->zoom == 2) return false;
-			vp->zoom++;
+			if (vp->zoom == ZOOM_LVL_MAX) return false;
+			vp->zoom = (ZoomLevel)((byte)vp->zoom + 1);
 
 			WP(w,vp_d).scrollpos_x -= vp->virtual_width >> 1;
 			WP(w,vp_d).scrollpos_y -= vp->virtual_height >> 1;
@@ -930,12 +932,13 @@
 	const Player *p = GetPlayer(_local_player);
 	Window *w2;
 	w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
-	WP(w2,menu_d).sel_index = _last_built_railtype;
+	WP(w2, menu_d).sel_index = _last_built_railtype;
 }
 
 static void ToolbarBuildRoadClick(Window *w)
 {
-	PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 1, 0);
+	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 1, 0);
+	WP(w2, menu_d).sel_index = _last_built_roadtype;
 }
 
 static void ToolbarBuildWaterClick(Window *w)
@@ -1049,7 +1052,7 @@
 	vp = w->viewport;
 
 	if (_game_mode != GM_MENU) {
-		if ((in && vp->zoom == 0) || (!in && vp->zoom == 2))
+		if ((in && vp->zoom == ZOOM_LVL_MIN) || (!in && vp->zoom == ZOOM_LVL_MAX))
 			return;
 
 		pt = GetTileZoomCenterWindow(in,w);
@@ -1128,7 +1131,7 @@
 
 static void PlaceProc_RockyArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_RockyArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_ROCKS);
 }
 
 static void PlaceProc_LightHouse(TileIndex tile)
@@ -1155,12 +1158,12 @@
 
 static void PlaceProc_DesertArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DesertArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_DESERT);
 }
 
 static void PlaceProc_WaterArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_WaterArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CREATE_WATER);
 }
 
 static const Widget _scen_edit_land_gen_widgets[] = {
@@ -1374,13 +1377,20 @@
 		_place_proc(e->we.place.tile);
 		break;
 	case WE_PLACE_DRAG:
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata & 0xF);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		break;
 
 	case WE_PLACE_MOUSEUP:
 		if (e->we.place.pt.x != -1) {
-			if ((e->we.place.userdata & 0xF) == VPM_X_AND_Y) // dragged actions
-				GUIPlaceProcDragXY(e);
+			switch (e->we.place.select_proc) {
+				case DDSP_CREATE_ROCKS:
+				case DDSP_CREATE_DESERT:
+				case DDSP_CREATE_WATER:
+				case DDSP_LEVEL_AREA:
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(e);
+					break;
+			}
 		}
 		break;
 
@@ -1873,7 +1883,7 @@
 		case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break;
 		case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break;
 		case WKC_SHIFT | WKC_F7: ShowBuildRailToolbar(_last_built_railtype, -1); break;
-		case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(); break;
+		case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break;
 		case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break;
 		case WKC_SHIFT | WKC_F10:ShowBuildAirToolbar(); break;
 		case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
@@ -2425,8 +2435,8 @@
 				_scrolling_viewport = false;
 			}
 
-			WP(w, vp_d).scrollpos_x += e->we.scroll.delta.x << vp->zoom;
-			WP(w, vp_d).scrollpos_y += e->we.scroll.delta.y << vp->zoom;
+			WP(w, vp_d).scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
+			WP(w, vp_d).scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
 		} break;
 
 		case WE_MOUSEWHEEL:
@@ -2460,7 +2470,7 @@
 	height = _screen.height;
 
 	w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
-	AssignWindowViewport(w, 0, 0, width, height, TileXY(32, 32), 0);
+	AssignWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
 
 	/* XXX: these are not done */
 	switch (_game_mode) {
@@ -2514,6 +2524,7 @@
 {
 	/* Clean old GUI values */
 	_last_built_railtype = RAILTYPE_RAIL;
+	_last_built_roadtype = ROADTYPE_ROAD;
 }
 
 
--- a/src/misc.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/misc.cpp	Fri May 25 00:25:08 2007 +0000
@@ -22,6 +22,7 @@
 #include "newgrf_house.h"
 #include "date.h"
 #include "cargotype.h"
+#include "group.h"
 
 char _name_array[512][32];
 
@@ -120,6 +121,7 @@
 	InitializeWaypoints();
 	InitializeDepots();
 	InitializeOrders();
+	InitializeGroup();
 
 	InitNewsItemStructs();
 	InitializeLandscape();
--- a/src/misc_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/misc_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -382,16 +382,16 @@
 	} break;
 
 	case WE_PLACE_OBJ:
-		VpStartPlaceSizing(e->we.place.tile, VPM_X_AND_Y_LIMITED);
+		VpStartPlaceSizing(e->we.place.tile, VPM_X_AND_Y_LIMITED, DDSP_PLANT_TREES);
 		VpSetPlaceSizingLimit(20);
 		break;
 
 	case WE_PLACE_DRAG:
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		return;
 
 	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1) {
+		if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_PLANT_TREES) {
 			DoCommandP(e->we.place.tile, _tree_to_plant, e->we.place.starttile, NULL,
 				CMD_PLANT_TREE | CMD_AUTO | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE));
 		}
@@ -579,11 +579,11 @@
 			vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
 
 			/* move x pos to opposite corner */
-			pt.x = ((pt.x - vp->virtual_left) >> vp->zoom) + vp->left;
+			pt.x = UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left;
 			pt.x = (pt.x < (_screen.width >> 1)) ? _screen.width - 260 : 20;
 
 			/* move y pos to opposite corner */
-			pt.y = ((pt.y - vp->virtual_top) >> vp->zoom) + vp->top;
+			pt.y = UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top;
 			pt.y = (pt.y < (_screen.height >> 1)) ? _screen.height - 80 : 100;
 
 		} else {
@@ -595,8 +595,8 @@
 		if ( (x|y) != 0) {
 			pt = RemapCoords2(x, y);
 			vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
-			pt.x = clamp(((pt.x - vp->virtual_left) >> vp->zoom) + vp->left - (334/2), 0, _screen.width - 334);
-			pt.y = clamp(((pt.y - vp->virtual_top) >> vp->zoom) + vp->top - (137/2), 22, _screen.height - 137);
+			pt.x = clamp(UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left - (334/2), 0, _screen.width - 334);
+			pt.y = clamp(UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top - (137/2), 22, _screen.height - 137);
 		} else {
 			pt.x = (_screen.width - 334) >> 1;
 			pt.y = (_screen.height - 137) >> 1;
--- a/src/network/network_server.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/network/network_server.cpp	Fri May 25 00:25:08 2007 +0000
@@ -1301,9 +1301,7 @@
 				_network_player_info[v->owner].num_vehicle[4]++;
 				break;
 
-			case VEH_SPECIAL:
-			case VEH_DISASTER:
-				break;
+			default: break;
 		}
 	}
 
--- a/src/newgrf.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf.cpp	Fri May 25 00:25:08 2007 +0000
@@ -40,6 +40,7 @@
 #include "cargotype.h"
 #include "industry.h"
 #include "newgrf_canal.h"
+#include "newgrf_commons.h"
 
 /* TTDPatch extended GRF format codec
  * (c) Petr Baudis 2004 (GPL'd)
@@ -531,6 +532,10 @@
 			FOR_EACH_OBJECT rvi[i].user_def_data = grf_load_byte(&buf);
 			break;
 
+		case 0x26: // Retire vehicle early
+			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
+			break;
+
 		case 0x27: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
@@ -553,7 +558,6 @@
 		/* @todo air drag and retire vehicle early
 		 * Fall-through for unimplemented one byte long properties. */
 		case 0x20: // Air drag
-		case 0x26: // Retire vehicle early
 			FOR_EACH_OBJECT grf_load_byte(&buf);
 			ret = true;
 			break;
@@ -650,6 +654,10 @@
 			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
 			break;
 
+		case 0x1B: // Retire vehicle early
+			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
+			break;
+
 		case 0x1C: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
@@ -671,7 +679,6 @@
 
 		case 0x18: // Tractive effort
 		case 0x19: // Air drag
-		case 0x1B: // Retire vehicle early
 			/* @todo */
 			FOR_EACH_OBJECT grf_load_byte(&buf);
 			ret = true;
@@ -758,6 +765,10 @@
 			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
 			break;
 
+		case 0x16: // Retire vehicle early
+			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
+			break;
+
 		case 0x17: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
@@ -779,7 +790,6 @@
 
 		case 0x14: // Ocean speed fraction
 		case 0x15: // Canal speed fraction
-		case 0x16: // Retire vehicle early
 			/* @todo */
 			FOR_EACH_OBJECT grf_load_byte(&buf);
 			ret = true;
@@ -871,6 +881,10 @@
 			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
 			break;
 
+		case 0x16: // Retire vehicle early
+			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
+			break;
+
 		case 0x17: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
@@ -890,12 +904,6 @@
 			FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
 			break;
 
-		case 0x16: // Retire vehicle early
-			/* @todo */
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
 		default:
 			ret = true;
 			break;
@@ -1239,7 +1247,7 @@
 		_cur_grffile->housespec = CallocT<HouseSpec*>(HOUSE_MAX);
 
 		/* Reset any overrides that have been set. */
-		ResetHouseOverrides();
+		_house_mngr.ResetOverride();
 	}
 
 	housespec = &_cur_grffile->housespec[hid];
@@ -1365,7 +1373,7 @@
 					return false;
 				}
 
-				AddHouseOverride(hid, override);
+				_house_mngr.Add(hid, override);
 			}
 			break;
 
@@ -1429,6 +1437,10 @@
 			}
 			break;
 
+		case 0x1F: // Minimum life span
+			FOR_EACH_OBJECT housespec[i]->minimum_life = grf_load_byte(&buf);
+			break;
+
 		default:
 			ret = true;
 			break;
@@ -2196,7 +2208,7 @@
 			} while (HASBIT(varadjust, 5));
 
 			group->g.determ.num_ranges = grf_load_byte(&buf);
-			group->g.determ.ranges = CallocT<DeterministicSpriteGroupRange>(group->g.determ.num_ranges);
+			if (group->g.determ.num_ranges > 0) group->g.determ.ranges = CallocT<DeterministicSpriteGroupRange>(group->g.determ.num_ranges);
 
 			if (!check_length(bufend - buf, 2 + (2 + 2 * varsize) * group->g.determ.num_ranges, "NewSpriteGroup (Deterministic)")) return;
 
@@ -2758,64 +2770,59 @@
 
 		len -= (int)name_length;
 
-		if (name_length == 1) {
-			grfmsg(7, "FeatureNewName: Can't add empty name");
-		} else {
-			grfmsg(8, "FeatureNewName: %d <- %s", id, name);
-
-			switch (feature) {
-				case GSF_TRAIN:
-				case GSF_ROAD:
-				case GSF_SHIP:
-				case GSF_AIRCRAFT: {
-					if (id < TOTAL_NUM_ENGINES) {
-						StringID string = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_8000_KIRBY_PAUL_TANK_STEAM + id);
-						SetCustomEngineName(id, string);
-					} else {
-						AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id);
-					}
-					break;
+		grfmsg(8, "FeatureNewName: 0x%04X <- %s", id, name);
+
+		switch (feature) {
+			case GSF_TRAIN:
+			case GSF_ROAD:
+			case GSF_SHIP:
+			case GSF_AIRCRAFT:
+				if (id < TOTAL_NUM_ENGINES) {
+					StringID string = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_8000_KIRBY_PAUL_TANK_STEAM + id);
+					SetCustomEngineName(id, string);
+				} else {
+					AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id);
 				}
-
-				case GSF_TOWNHOUSE:
-				default:
-					switch (GB(id, 8, 8)) {
-						case 0xC4: // Station class name
-							if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
-								grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
-							} else {
-								StationClassID sclass = _cur_grffile->stations[GB(id, 0, 8)]->sclass;
-								SetStationClassName(sclass, AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED));
-							}
-							break;
-
-						case 0xC5: // Station name
-							if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
-								grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
-							} else {
-								_cur_grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
-							}
-							break;
-
-						case 0xC9: { // House name
-							if (_cur_grffile->housespec == NULL || _cur_grffile->housespec[GB(id, 0, 8)] == NULL) {
-								grfmsg(1, "FeatureNewName: Attempt to name undefined house 0x%X, ignoring.", GB(id, 0, 8));
-							} else {
-								_cur_grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
-							}
-							break;
+				break;
+
+			case GSF_TOWNHOUSE:
+			default:
+				switch (GB(id, 8, 8)) {
+					case 0xC4: // Station class name
+						if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
+							grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
+						} else {
+							StationClassID sclass = _cur_grffile->stations[GB(id, 0, 8)]->sclass;
+							SetStationClassName(sclass, AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED));
 						}
-
-						case 0xD0:
-						case 0xDC:
-							AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
-							break;
-
-						default:
-							grfmsg(7, "FeatureNewName: Unsupported ID (0x%04X)", id);
-							break;
-					}
-					break;
+						break;
+
+					case 0xC5: // Station name
+						if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
+							grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
+						} else {
+							_cur_grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+						}
+						break;
+
+					case 0xC9: // House name
+						if (_cur_grffile->housespec == NULL || _cur_grffile->housespec[GB(id, 0, 8)] == NULL) {
+							grfmsg(1, "FeatureNewName: Attempt to name undefined house 0x%X, ignoring.", GB(id, 0, 8));
+						} else {
+							_cur_grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+						}
+						break;
+
+					case 0xD0:
+					case 0xDC:
+						AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+						break;
+
+					default:
+						grfmsg(7, "FeatureNewName: Unsupported ID (0x%04X)", id);
+						break;
+				}
+				break;
 
 #if 0
 				case GSF_CANAL :
@@ -2836,7 +2843,6 @@
 					grfmsg(7, "FeatureNewName: Unsupported feature (0x%02X)", feature);
 					break;
 #endif
-			}
 		}
 	}
 }
@@ -3088,11 +3094,18 @@
 
 		grfmsg(8, "CfgApply: Applying %u bytes from parameter 0x%02X at offset 0x%04X", param_size, param_num, offset);
 
+		bool carry = false;
 		for (i = 0; i < param_size; i++) {
 			uint32 value = GetParamVal(param_num + i / 4, NULL);
+			/* Reset carry flag for each iteration of the variable (only really
+			 * matters if param_size is greater than 4) */
+			if (i == 0) carry = false;
 
 			if (add_value) {
-				_preload_sprite[offset + i] += GB(value, (i % 4) * 8, 8);
+				uint new_value = _preload_sprite[offset + i] + GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
+				_preload_sprite[offset + i] = GB(new_value, 0, 8);
+				/* Check if the addition overflowed */
+				carry = new_value >= 256;
 			} else {
 				_preload_sprite[offset + i] = GB(value, (i % 4) * 8, 8);
 			}
@@ -3193,6 +3206,10 @@
 				break;
 			case 5: result = (param_val & mask) > cond_val;
 				break;
+			case 11: result = GetCargoIDByLabel(BSWAP32(cond_val)) == CT_INVALID;
+				break;
+			case 12: result = GetCargoIDByLabel(BSWAP32(cond_val)) != CT_INVALID;
+				break;
 
 			default: grfmsg(1, "SkipIf: Unsupported test %d. Ignoring", condtype); return;
 		}
@@ -4208,7 +4225,7 @@
 	                   |                                        (1 << 0x05)  // resolutionwidth
 	                   |                                        (1 << 0x06)  // resolutionheight
 	                   |                                        (0 << 0x07)  // newindustries
-	                   |                                        (0 << 0x08)  // fifoloading
+	                   |         ((_patches.improved_load ? 1 : 0) << 0x08)  // fifoloading
 	                   |                                        (0 << 0x09)  // townroadbranchprob
 	                   |                                        (0 << 0x0A)  // tempsnowline
 	                   |                                        (1 << 0x0B)  // newcargo
@@ -4544,6 +4561,8 @@
 		/* Check if this engine's cargo type is valid. If not, set to the first refittable
 		 * cargo type. Apparently cargo_type isn't a common property... */
 		switch (GetEngine(engine)->type) {
+			default: NOT_REACHED();
+			case VEH_AIRCRAFT: break;
 			case VEH_TRAIN: {
 				RailVehicleInfo *rvi = &_rail_vehicle_info[engine];
 				if (rvi->cargo_type == CT_INVALID) rvi->cargo_type = FindFirstRefittableCargo(engine);
@@ -4586,7 +4605,7 @@
 		for (int i = 0; i < HOUSE_MAX; i++) {
 			HouseSpec *hs = file->housespec[i];
 			if (hs != NULL) {
-				SetHouseSpec(hs);
+				_house_mngr.SetEntitySpec(hs);
 				if (hs->min_date < 1930) reset_dates = false;
 			}
 		}
--- a/src/newgrf_cargo.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_cargo.cpp	Fri May 25 00:25:08 2007 +0000
@@ -39,10 +39,12 @@
 
 static const SpriteGroup *CargoResolveReal(const ResolverObject *object, const SpriteGroup *group)
 {
-	/* Cargo action 2s should always have only 1 "loaded" state */
-	if (group->g.real.num_loaded == 0) return NULL;
+	/* Cargo action 2s should always have only 1 "loaded" state, but some
+	 * times things don't follow the spec... */
+	if (group->g.real.num_loaded > 0) return group->g.real.loaded[0];
+	if (group->g.real.num_loading > 0) return group->g.real.loading[0];
 
-	return group->g.real.loaded[0];
+	return NULL;
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_commons.cpp	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,150 @@
+/* $Id$ */
+
+/** @file newgrf_commons.cpp Implementation of the class OverrideManagerBase
+ * and its descendance, present and futur
+ */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "town.h"
+#include "industry.h"
+#include "newgrf.h"
+#include "newgrf_commons.h"
+
+/** Constructor of generic class
+ * @param offset end of original data for this entity. i.e: houses = 110
+ * @param maximum of entities this manager can deal with. i.e: houses = 512
+ * @param invalid is the ID used to identify an invalid entity id
+ */
+OverrideManagerBase::OverrideManagerBase(uint16 offset, uint16 maximum, uint16 invalid)
+{
+	max_offset = offset;
+	max_new_entities = maximum;
+	invalid_ID = invalid;
+
+	mapping_ID = CallocT<EntityIDMapping>(max_new_entities);
+	entity_overrides = MallocT<uint16>(max_offset);
+	memset(entity_overrides, invalid, sizeof(entity_overrides));
+}
+
+/** Destructor of the generic class.
+ * Frees allocated memory of constructor
+ */
+OverrideManagerBase::~OverrideManagerBase()
+{
+	free(mapping_ID);
+	free(entity_overrides);
+}
+
+/** Since the entity IDs defined by the GRF file does not necessarily correlate
+ * to those used by the game, the IDs used for overriding old entities must be
+ * translated when the entity spec is set.
+ * @param local_id id in grf file
+ * @param entity_type original entity type
+ */
+void OverrideManagerBase::Add(uint8 local_id, uint entity_type)
+{
+	assert(entity_type < max_offset);
+	entity_overrides[entity_type] = local_id;
+}
+
+/** Resets the mapping, which is used while initializing game */
+void OverrideManagerBase::ResetMapping()
+{
+	memset(mapping_ID, 0, (max_new_entities - 1) * sizeof(EntityIDMapping));
+}
+
+/** Resets the override, which is used while initializing game */
+void OverrideManagerBase::ResetOverride()
+{
+	for (uint16 i = 0; i < max_offset; i++) {
+		entity_overrides[i] = invalid_ID;
+	}
+}
+
+/** Return the ID (if ever available) of a previously inserted entity.
+ * @param grf_local_id ID of this enity withing the grfID
+ * @param grfid ID of the grf file
+ * @return the ID of the candidate, of the Invalid flag item ID
+ */
+uint16 OverrideManagerBase::GetID(uint8 grf_local_id, uint32 grfid)
+{
+	const EntityIDMapping *map;
+
+	for (uint16 id = max_offset; id < max_new_entities; id++) {
+		map = &mapping_ID[id];
+		if (map->entity_id == grf_local_id && map->grfid == grfid) {
+			return id;
+		}
+	}
+	return invalid_ID;
+}
+
+/** Reserves a place in the mapping array for an entity to be installed
+ * @param grf_local_id is an arbitrary id given by the grf's author.  Also known as setid
+ * @param grfid is the id of the grf file itself
+ * @param substitute_id is the original entity from which data is copied for the new one
+ * @return the proper usable slot id, or invalid marker if none is found
+ */
+uint16 OverrideManagerBase::AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id)
+{
+	uint16 id = this->GetID(grf_local_id, grfid);
+	EntityIDMapping *map;
+
+	/* Look to see if this entity has already been added. This is done
+	 * separately from the loop below in case a GRF has been deleted, and there
+	 * are any gaps in the array.
+	 */
+	if (id != invalid_ID) {
+		return id;
+	}
+
+	/* This entity hasn't been defined before, so give it an ID now. */
+	for (id = max_offset; id < max_new_entities; id++) {
+		map = &mapping_ID[id];
+
+		if (map->entity_id == 0 && map->grfid == 0) {
+			map->entity_id     = grf_local_id;
+			map->grfid         = grfid;
+			map->substitute_id = substitute_id;
+			return id;
+		}
+	}
+
+	return invalid_ID;
+}
+
+/** Gives the substitute of the entity, as specified by the grf file
+ * @param entity_id of the entity being queried
+ * @return mapped id
+ */
+uint16 OverrideManagerBase::GetSubstituteID(byte entity_id)
+{
+	return mapping_ID[entity_id].substitute_id;
+}
+
+/** Install the specs into the HouseSpecs array
+ * It will find itself the proper slot onwhich it will go
+ * @param hs HouseSpec read from the grf file, ready for inclusion
+ */
+void HouseOverrideManager::SetEntitySpec(const HouseSpec *hs)
+{
+	HouseID house_id = this->AddEntityID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
+
+	if (house_id == invalid_ID) {
+		grfmsg(1, "House.SetEntitySpec: Too many houses allocated. Ignoring.");
+		return;
+	}
+
+	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
+
+	/* Now add the overrides. */
+	for (int i = 0; i != max_offset; i++) {
+		HouseSpec *overridden_hs = GetHouseSpecs(i);
+
+		if (entity_overrides[i] != hs->local_id) continue;
+
+		overridden_hs->override = house_id;
+		entity_overrides[i] = invalid_ID;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/newgrf_commons.h	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,69 @@
+/* $Id$ */
+
+/** @file newgrf_commons.h This file simplyfies and embeds a common mechanism of
+ * loading/saving and mapping of grf entities.
+ */
+
+#ifndef NEWGRF_COMMONS_H
+#define NEWGRF_COMMONS_H
+
+/**
+ * Maps an entity id stored on the map to a GRF file.
+ * Entities are objects used ingame (houses, industries, industry tiles) for
+ * which we need to correlate the ids from the grf files with the ones in the
+ * the savegames themselves.
+ * An array of EntityIDMapping structs is saved with the savegame so
+ * that those GRFs can be loaded in a different order, or removed safely. The
+ * index in the array is the entity's ID stored on the map.
+ *
+ * The substitute ID is the ID of an original entity that should be used instead
+ * if the GRF containing the new entity is not available.
+ */
+struct EntityIDMapping {
+	uint32 grfid;          ///< The GRF ID of the file the entity belongs to
+	uint8  entity_id;      ///< The entity ID within the GRF file
+	uint8  substitute_id;  ///< The (original) entity ID to use if this GRF is not available
+};
+
+class OverrideManagerBase
+{
+protected:
+	uint16 *entity_overrides;
+
+	uint16 max_offset;       ///< what is the length of the original entity's array of specs
+	uint16 max_new_entities; ///< what is the amount of entities, old and new summed
+
+	uint16 invalid_ID;       ///< ID used to dected invalid entities;
+
+	virtual uint16 AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id);
+public:
+	EntityIDMapping *mapping_ID; ///< mapping of ids from grf files.  Public out of convenience
+
+	OverrideManagerBase(uint16 offset, uint16 maximum, uint16 invalid);
+	virtual ~OverrideManagerBase();
+
+	void ResetOverride();
+	void ResetMapping();
+
+	void Add(uint8 local_id, uint entity_type);
+
+	uint16 GetSubstituteID(byte entity_id);
+	uint16 GetID(uint8 grf_local_id, uint32 grfid);
+
+	inline uint16 GetMaxMapping() { return max_new_entities; };
+	inline uint16 GetMaxOffset() { return max_offset; };
+};
+
+
+struct HouseSpec;
+class HouseOverrideManager : public OverrideManagerBase
+{
+public:
+	HouseOverrideManager(uint16 offset, uint16 maximum, uint16 invalid) : OverrideManagerBase(offset, maximum, invalid) {};
+	void SetEntitySpec(const HouseSpec *hs);
+};
+
+
+extern HouseOverrideManager _house_mngr;
+
+#endif /* NEWGRF_COMMONS_H */
--- a/src/newgrf_engine.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_engine.cpp	Fri May 25 00:25:08 2007 +0000
@@ -63,22 +63,22 @@
 	memcpy(wo->train_id, train_id, trains);
 }
 
-static const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
+const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
 {
 	const WagonOverrides *wos = &_engine_wagon_overrides[engine];
-	int i;
 
 	/* XXX: This could turn out to be a timesink on profiles. We could
 	 * always just dedicate 65535 bytes for an [engine][train] trampoline
 	 * for O(1). Or O(logMlogN) and searching binary tree or smt. like
 	 * that. --pasky */
 
-	for (i = 0; i < wos->overrides_count; i++) {
+	for (int i = 0; i < wos->overrides_count; i++) {
 		const WagonOverride *wo = &wos->overrides[i];
-		int j;
 
-		for (j = 0; j < wo->trains; j++) {
-			if (wo->train_id[j] == overriding_engine && (wo->cargo == cargo || wo->cargo == CT_DEFAULT)) return wo->group;
+		if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
+
+		for (int j = 0; j < wo->trains; j++) {
+			if (wo->train_id[j] == overriding_engine) return wo->group;
 		}
 	}
 	return NULL;
@@ -246,7 +246,7 @@
 {
 	const Station *st = GetStation(v->u.air.targetairport);
 	const AirportFTAClass *afc = st->Airport();
-	byte amdflag = afc->MovingData(v->u.air.pos)->flag;
+	uint16 amdflag = afc->MovingData(v->u.air.pos)->flag;
 
 	switch (v->u.air.state) {
 		case HANGAR:
@@ -313,7 +313,7 @@
 			}
 
 		case FLYING:
-			return AMS_TTDP_FLIGHT_TO_TOWER;
+			return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
 
 		case LANDING: // Descent
 			return AMS_TTDP_FLIGHT_DESCENT;
@@ -770,6 +770,8 @@
 				case 0x66: return MapAircraftMovementAction(v); // Current movement action
 			}
 			break;
+
+		default: break;
 	}
 
 	DEBUG(grf, 1, "Unhandled vehicle property 0x%X, type 0x%X", variable, v->type);
@@ -850,8 +852,7 @@
 		cargo = v->cargo_type;
 
 		if (v->type == VEH_TRAIN) {
-			group = GetWagonOverrideSpriteSet(engine, cargo, v->u.rail.first_engine);
-
+			group = v->u.rail.cached_override;
 			if (group != NULL) return group;
 		}
 	}
@@ -912,7 +913,7 @@
 bool UsesWagonOverride(const Vehicle* v)
 {
 	assert(v->type == VEH_TRAIN);
-	return GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->u.rail.first_engine) != NULL;
+	return v->u.rail.cached_override != NULL;
 }
 
 /**
--- a/src/newgrf_engine.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_engine.h	Fri May 25 00:25:08 2007 +0000
@@ -14,6 +14,7 @@
 
 
 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const struct SpriteGroup *group, byte *train_id, int trains);
+const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine);
 void SetCustomEngineSprites(EngineID engine, byte cargo, const struct SpriteGroup *group);
 void SetRotorOverrideSprites(EngineID engine, const struct SpriteGroup *group);
 SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle* v, Direction direction);
--- a/src/newgrf_house.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_house.cpp	Fri May 25 00:25:08 2007 +0000
@@ -24,92 +24,12 @@
 #include "newgrf_callbacks.h"
 #include "newgrf_town.h"
 #include "newgrf_sound.h"
+#include "newgrf_commons.h"
 
 static BuildingCounts    _building_counts;
 static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
-HouseIDMapping _house_id_mapping[HOUSE_MAX];
-
-/* Since the house IDs defined by the GRF file don't necessarily correlate
- * to those used by the game, the IDs used for overriding old houses must be
- * translated when the house spec is set. */
-static uint16 _house_overrides[NEW_HOUSE_OFFSET];
-
-void AddHouseOverride(uint8 local_id, uint house_type)
-{
-	assert(house_type < NEW_HOUSE_OFFSET);
-	_house_overrides[house_type] = local_id;
-}
-
-void ResetHouseOverrides()
-{
-	for (int i = 0; i != lengthof(_house_overrides); i++) {
-		_house_overrides[i] = INVALID_HOUSE_ID;
-	}
-}
-
-static HouseID GetHouseID(byte grf_local_id, uint32 grfid)
-{
-	const HouseIDMapping *map;
-
-	for (HouseID house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
-		map = &_house_id_mapping[house_id];
-		if (map->house_id == grf_local_id && map->grfid == grfid) return house_id;
-	}
-	return INVALID_HOUSE_ID;
-}
-
-static HouseID AddHouseID(byte grf_local_id, uint32 grfid, byte substitute_id)
-{
-	HouseID house_id;
-	HouseIDMapping *map;
 
-	/* Look to see if this house has already been added. This is done
-	 * separately from the loop below in case a GRF has been deleted, and there
-	 * are any gaps in the array. */
-	house_id = GetHouseID(grf_local_id, grfid);
-	if (house_id != INVALID_HOUSE_ID) return house_id;
-
-	/* This house hasn't been defined before, so give it an ID now. */
-	for (house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
-		map = &_house_id_mapping[house_id];
-
-		if (map->house_id == 0 && map->grfid == 0) {
-			map->house_id      = grf_local_id;
-			map->grfid         = grfid;
-			map->substitute_id = substitute_id;
-			return house_id;
-		}
-	}
-
-	return INVALID_HOUSE_ID;
-}
-
-void SetHouseSpec(const HouseSpec *hs)
-{
-	HouseID house_id = AddHouseID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
-
-	if (house_id == INVALID_HOUSE_ID) {
-		grfmsg(1, "SetHouseSpec: Too many houses allocated. Ignoring.");
-		return;
-	}
-
-	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
-
-	/* Now add the overrides. */
-	for (int i = 0; i != lengthof(_house_overrides); i++) {
-		HouseSpec *overridden_hs = GetHouseSpecs(i);
-
-		if (_house_overrides[i] != hs->local_id) continue;
-
-		overridden_hs->override = house_id;
-		_house_overrides[i] = INVALID_HOUSE_ID;
-	}
-}
-
-void ResetHouseIDMapping()
-{
-	memset(&_house_id_mapping, 0, sizeof(_house_id_mapping));
-}
+HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, HOUSE_MAX, INVALID_HOUSE_ID);
 
 void CheckHouseIDs()
 {
@@ -122,7 +42,7 @@
 		if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
 			/* The specs for this type of house are not available any more, so
 			 * replace it with the substitute original house type. */
-			SetHouseType(t, _house_id_mapping[house_id].substitute_id);
+			SetHouseType(t, _house_mngr.GetSubstituteID(house_id));
 		}
 	}
 
@@ -313,7 +233,7 @@
 			const HouseSpec *hs = GetHouseSpecs(house_id);
 			if (hs->grffile == NULL) return 0;
 
-			HouseID new_house = GetHouseID(parameter, hs->grffile->grfid);
+			HouseID new_house = _house_mngr.GetID(parameter, hs->grffile->grfid);
 			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, town);
 		}
 
@@ -374,7 +294,7 @@
 	res->reseed          = 0;
 }
 
-uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile)
+uint16 GetHouseCallback(uint16 callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile)
 {
 	ResolverObject object;
 	const SpriteGroup *group;
@@ -382,7 +302,7 @@
 	NewHouseResolver(&object, house_id, tile, town);
 	object.callback = callback;
 	object.callback_param1 = param1;
-	object.callback_param2 = 0;
+	object.callback_param2 = param2;
 
 	group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
 	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
@@ -413,7 +333,7 @@
 			if (pal == 0) {
 				const HouseSpec *hs = GetHouseSpecs(house_id);
 				if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) {
-					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, house_id, GetTownByTile(ti->tile), ti->tile);
+					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile);
 					if (callback != CALLBACK_FAILED) {
 						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
 						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
@@ -468,7 +388,7 @@
 	bool frame_set_by_callback = false;
 
 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) {
-		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
 	}
 
@@ -483,7 +403,7 @@
 
 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) {
 		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
-		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
 		if (callback_res != CALLBACK_FAILED) {
 			frame_set_by_callback = true;
@@ -549,7 +469,7 @@
 			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
 
 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
-		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		return (callback_res == CALLBACK_FAILED || callback_res == 0);
 	} else {
 		return !(hs->extra_flags & BUILDING_IS_PROTECTED);
@@ -562,7 +482,7 @@
 
 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
 		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
-		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
 		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
 	}
@@ -577,7 +497,11 @@
 		return true;
 	}
 
-	/* @todo: Magic with triggers goes here.  Got to implement that, one day. .. */
+	/* @todo: Magic with triggers goes here.  Got to implement that, one day. ..
+	 * Process randomizing of tiles following specs.
+	 * Once done, redraw the house
+	 * MarkTileDirtyByTile(tile);
+	 */
 
 	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
 		/* If this house is marked as having a synchronised callback, all the
@@ -598,7 +522,7 @@
 
 	/* Check callback 21, which determines if a house should be destroyed. */
 	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
-		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
 			ClearTownHouse(GetTownByTile(tile), tile);
 			return false;
--- a/src/newgrf_house.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_house.h	Fri May 25 00:25:08 2007 +0000
@@ -41,15 +41,7 @@
 	uint8  class_id;  ////< The class id within the grf file
 };
 
-extern HouseIDMapping _house_id_mapping[HOUSE_MAX]; ///< Declared in newgrf_house.cpp
-
-void AddHouseOverride(uint8 local_id, uint house_type);
-void ResetHouseOverrides();
-
-void SetHouseSpec(const HouseSpec *hs);
-
 void CheckHouseIDs();
-void ResetHouseIDMapping();
 
 HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid);
 
@@ -62,7 +54,7 @@
 void AnimateNewHouseTile(TileIndex tile);
 void ChangeHouseAnimationFrame(TileIndex tile, uint16 callback_result);
 
-uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile);
+uint16 GetHouseCallback(uint16 callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile);
 
 bool CanDeleteHouse(TileIndex tile);
 
--- a/src/newgrf_spritegroup.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_spritegroup.cpp	Fri May 25 00:25:08 2007 +0000
@@ -129,10 +129,10 @@
 		case DSGA_OP_SMAX: return max((S)last_value, (S)value);
 		case DSGA_OP_UMIN: return min((U)last_value, (U)value);
 		case DSGA_OP_UMAX: return max((U)last_value, (U)value);
-		case DSGA_OP_SDIV: return (S)last_value / (S)value;
-		case DSGA_OP_SMOD: return (S)last_value % (S)value;
-		case DSGA_OP_UDIV: return (U)last_value / (U)value;
-		case DSGA_OP_UMOD: return (U)last_value % (U)value;
+		case DSGA_OP_SDIV: return value == 0 ? (S)last_value : (S)last_value / (S)value;
+		case DSGA_OP_SMOD: return value == 0 ? (S)last_value : (S)last_value % (S)value;
+		case DSGA_OP_UDIV: return value == 0 ? (U)last_value : (U)last_value / (U)value;
+		case DSGA_OP_UMOD: return value == 0 ? (U)last_value : (U)last_value % (U)value;
 		case DSGA_OP_MUL:  return last_value * value;
 		case DSGA_OP_AND:  return last_value & value;
 		case DSGA_OP_OR:   return last_value | value;
--- a/src/newgrf_station.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/newgrf_station.cpp	Fri May 25 00:25:08 2007 +0000
@@ -307,7 +307,7 @@
 	uint i;
 
 	for (i = 0; i < lengthof(x_dir); i++, dir++, diagdir++) {
-		uint32 ts = GetTileTrackStatus(tile + TileOffsByDir(*dir), TRANSPORT_RAIL);
+		uint32 ts = GetTileTrackStatus(tile + TileOffsByDir(*dir), TRANSPORT_RAIL, 0);
 		if (ts != 0) {
 			/* If there is any track on the tile, set the bit in the second byte */
 			SETBIT(res, i + 8);
--- a/src/news_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/news_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -427,7 +427,7 @@
 			w = AllocateWindowDesc(&_news_type13_desc);
 			if (ni->flags & NF_VIEWPORT)
 				AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E,
-					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0);
+					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
 			break;
 		}
 
@@ -436,7 +436,7 @@
 			w = AllocateWindowDesc(&_news_type2_desc);
 			if (ni->flags & NF_VIEWPORT)
 				AssignWindowViewport(w, 2, 58, 0x1AA, 0x46,
-					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0);
+					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
 			break;
 		}
 
@@ -445,7 +445,7 @@
 			w = AllocateWindowDesc(&_news_type0_desc);
 			if (ni->flags & NF_VIEWPORT)
 				AssignWindowViewport(w, 3, 17, 0x112, 0x2F,
-					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0);
+					ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
 			break;
 		}
 	}
--- a/src/npf.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/npf.cpp	Fri May 25 00:25:08 2007 +0000
@@ -523,6 +523,7 @@
 	uint32 ts;
 	TrackdirBits trackdirbits;
 	TransportType type = (TransportType)aystar->user_data[NPF_TYPE];
+	uint subtype = aystar->user_data[NPF_SUB_TYPE];
 	bool override_dst_check = false;
 	/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
 	aystar->num_neighbours = 0;
@@ -622,7 +623,7 @@
 		 * the back */
 		ts = TrackdirToTrackdirBits(DiagdirToDiagTrackdir(ReverseDiagDir(exitdir)));
 	} else {
-		ts = GetTileTrackStatus(dst_tile, type);
+		ts = GetTileTrackStatus(dst_tile, type, subtype);
 	}
 	trackdirbits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK); /* Filter out signal status and the unused bits */
 
@@ -670,7 +671,7 @@
  * multiple targets that are spread around, we should perform a breadth first
  * search by specifiying CalcZero as our heuristic.
  */
-static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
+static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
 {
 	int r;
 	NPFFoundTargetData result;
@@ -709,6 +710,7 @@
 
 	/* Initialize user_data */
 	_npf_aystar.user_data[NPF_TYPE] = type;
+	_npf_aystar.user_data[NPF_SUB_TYPE] = sub_type;
 	_npf_aystar.user_data[NPF_OWNER] = owner;
 	_npf_aystar.user_data[NPF_RAILTYPES] = railtypes;
 
@@ -728,7 +730,7 @@
 	return result;
 }
 
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -742,15 +744,15 @@
 	start2.direction = trackdir2;
 	start2.user_data[NPF_TRACKDIR_CHOICE] = INVALID_TRACKDIR;
 
-	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner, railtypes, 0);
+	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, sub_type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
 {
-	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, target, type, owner, railtypes);
+	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, target, type, sub_type, owner, railtypes);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -766,15 +768,15 @@
 
 	/* perform a breadth first search. Target is NULL,
 	 * since we are just looking for any depot...*/
-	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, owner, railtypes, reverse_penalty);
+	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, sub_type, owner, railtypes, reverse_penalty);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
 {
-	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, type, owner, railtypes, 0);
+	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, type, sub_type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
 {
 	/* Okay, what we're gonna do. First, we look at all depots, calculate
 	 * the manhatten distance to get to each depot. We then sort them by
@@ -823,6 +825,7 @@
 
 	/* Initialize user_data */
 	_npf_aystar.user_data[NPF_TYPE] = type;
+	_npf_aystar.user_data[NPF_SUB_TYPE] = sub_type;
 	_npf_aystar.user_data[NPF_OWNER] = owner;
 
 	/* Initialize Start Node */
--- a/src/npf.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/npf.h	Fri May 25 00:25:08 2007 +0000
@@ -46,6 +46,7 @@
 /* Indices into AyStar.userdata[] */
 enum {
 	NPF_TYPE = 0,  ///< Contains a TransportTypes value
+	NPF_SUB_TYPE,  ///< Contains the sub transport type
 	NPF_OWNER,     ///< Contains an Owner value
 	NPF_RAILTYPES, ///< Contains a bitmask the compatible RailTypes of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise.
 };
@@ -76,28 +77,28 @@
 /* Will search from the given tile and direction, for a route to the given
  * station for the given transport type. See the declaration of
  * NPFFoundTargetData above for the meaning of the result. */
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
 
 /* Will search as above, but with two start nodes, the second being the
  * reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which
  * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
 
 /* Will search a route to the closest depot. */
 
 /* Search using breadth first. Good for little track choice and inaccurate
  * heuristic, such as railway/road.*/
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
 /* Same as above but with two start nodes, the second being the reverse. Call
  * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
  * orginated. All pathfs from the second node will have the given
  * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
  * tile).
  */
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, Owner owner, RailTypeMask railtypes, uint reverse_penalty);
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty);
 /* Search by trying each depot in order of Manhattan Distance. Good for lots
  * of choices and accurate heuristics, such as water. */
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
 
 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 
--- a/src/oldloader.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/oldloader.cpp	Fri May 25 00:25:08 2007 +0000
@@ -329,6 +329,9 @@
 	FOR_ALL_VEHICLES(v) {
 		Vehicle *u;
 
+		/* We haven't used this bit for stations for ages */
+		if (v->type == VEH_ROAD) CLRBIT(v->u.road.state, RVS_IS_STOPPING);
+
 		FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
 			/* If a vehicle has the same orders, add the link to eachother
 			 * in both vehicles */
@@ -621,12 +624,7 @@
 };
 static bool LoadOldStation(LoadgameState *ls, int num)
 {
-	Station *st;
-
-	if (!AddBlockIfNeeded(&_Station_pool, num))
-		error("Stations: failed loading savegame: too many stations");
-
-	st = GetStation(num);
+	Station *st = new (num) Station();
 	_current_station_id = num;
 
 	if (!LoadChunk(ls, st, station_chunk))
@@ -653,8 +651,7 @@
 	OCL_VAR ( OC_UINT32,   1, &_old_town_index ),
 	OCL_SVAR(  OC_UINT8, Industry, width ),
 	OCL_SVAR(  OC_UINT8, Industry, height ),
-	OCL_SVAR(  OC_UINT8, Industry, produced_cargo[0] ),
-	OCL_SVAR(  OC_UINT8, Industry, produced_cargo[1] ),
+	OCL_NULL( 2 ),  ///< used to be industry's produced_cargo
 
 	OCL_SVAR( OC_UINT16, Industry, cargo_waiting[0] ),
 	OCL_SVAR( OC_UINT16, Industry, cargo_waiting[1] ),
@@ -662,9 +659,7 @@
 	OCL_SVAR(  OC_UINT8, Industry, production_rate[0] ),
 	OCL_SVAR(  OC_UINT8, Industry, production_rate[1] ),
 
-	OCL_SVAR(  OC_UINT8, Industry, accepts_cargo[0] ),
-	OCL_SVAR(  OC_UINT8, Industry, accepts_cargo[1] ),
-	OCL_SVAR(  OC_UINT8, Industry, accepts_cargo[2] ),
+	OCL_NULL( 3 ),  ///< used to be industry's accepts_cargo
 
 	OCL_SVAR(  OC_UINT8, Industry, prod_level ),
 
@@ -1407,6 +1402,19 @@
 
 	for (i = 0; i < OLD_MAP_SIZE; i ++) {
 		switch (GetTileType(i)) {
+			case MP_STATION:
+				_m[i].m4 = 0; // We do not understand this TTDP station mapping (yet)
+				switch (_m[i].m5) {
+					/* We have drive through stops at a totally different place */
+					case 0x53: case 0x54: _m[i].m5 += GFX_BUS_BASE_EXT   - 0x53; break;
+					case 0x57: case 0x58: _m[i].m5 += GFX_TRUCK_BASE_EXT - 0x57; break;
+					case 0x55: case 0x56: // Bus tram stop
+					case 0x59: case 0x5A: // Truck tram stop
+						DEBUG(oldloader, 0, "Loading failed - we don't support trams (yet)");
+						return false;
+				}
+				break;
+
 			case MP_RAILWAY:
 				/* We save presignals different from TTDPatch, convert them */
 				if (GetRailTileType(i) == RAIL_TILE_SIGNALS) {
--- a/src/openttd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/openttd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -62,7 +62,9 @@
 #include "newgrf.h"
 #include "newgrf_config.h"
 #include "newgrf_house.h"
+#include "newgrf_commons.h"
 #include "player_face.h"
+#include "group.h"
 
 #include "bridge_map.h"
 #include "clear_map.h"
@@ -300,6 +302,7 @@
 	CleanPool(&_Vehicle_pool);
 	CleanPool(&_Sign_pool);
 	CleanPool(&_Order_pool);
+	CleanPool(&_Group_pool);
 
 	free((void*)_town_sort);
 	free((void*)_industry_sort);
@@ -511,6 +514,8 @@
 	LoadDriver(MUSIC_DRIVER, _ini_musicdriver);
 	LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads
 	_savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
+	/* Initialize the zoom level of the screen to normal */
+	_screen.zoom = ZOOM_LVL_NORMAL;
 
 	/* restore saved music volume */
 	_music_driver->set_volume(msf.music_vol);
@@ -694,7 +699,7 @@
 	_game_mode = GM_NORMAL;
 
 	ResetGRFConfig(true);
-	ResetHouseIDMapping();
+	_house_mngr.ResetMapping();
 
 	GenerateWorldSetCallback(&MakeNewGameDone);
 	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
@@ -995,8 +1000,8 @@
 		Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
 		assert(w);
 
-		WP(w,vp_d).scrollpos_x += x << w->viewport->zoom;
-		WP(w,vp_d).scrollpos_y += y << w->viewport->zoom;
+		WP(w,vp_d).scrollpos_x += ScaleByZoom(x, w->viewport->zoom);
+		WP(w,vp_d).scrollpos_y += ScaleByZoom(y, w->viewport->zoom);
 	}
 }
 
@@ -1112,8 +1117,8 @@
 	for (tile = 0; tile != MapSize(); tile++) {
 		switch (GetTileType(tile)) {
 			case MP_STREET:
-				if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) & 0x80) {
-					SetCrossingRoadOwner(tile, OWNER_TOWN);
+				if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HASBIT(_m[tile].m4, 7)) {
+					_m[tile].m4 = OWNER_TOWN;
 				}
 				/* FALLTHROUGH */
 
@@ -1291,8 +1296,8 @@
 
 	vp = w->viewport;
 	vp->zoom = _saved_scrollpos_zoom;
-	vp->virtual_width = vp->width << vp->zoom;
-	vp->virtual_height = vp->height << vp->zoom;
+	vp->virtual_width = ScaleByZoom(vp->width, vp->zoom);
+	vp->virtual_height = ScaleByZoom(vp->height, vp->zoom);
 
 	/* in version 4.1 of the savegame, is_active was introduced to determine
 	 * if a player does exist, rather then checking name_1 */
@@ -1418,6 +1423,70 @@
 		}
 	}
 
+	if (CheckSavegameVersion(48)) {
+		for (TileIndex t = 0; t < map_size; t++) {
+			switch (GetTileType(t)) {
+				case MP_RAILWAY:
+					if (IsPlainRailTile(t)) {
+						/* Swap ground type and signal type for plain rail tiles, so the
+						 * ground type uses the same bits as for depots and waypoints. */
+						uint tmp = GB(_m[t].m4, 0, 4);
+						SB(_m[t].m4, 0, 4, GB(_m[t].m2, 0, 4));
+						SB(_m[t].m2, 0, 4, tmp);
+					} else if (HASBIT(_m[t].m5, 2)) {
+						/* Split waypoint and depot rail type and remove the subtype. */
+						CLRBIT(_m[t].m5, 2);
+						CLRBIT(_m[t].m5, 6);
+					}
+					break;
+
+				case MP_STREET:
+					/* Swap m3 and m4, so the track type for rail crossings is the
+					 * same as for normal rail. */
+					Swap(_m[t].m3, _m[t].m4);
+					break;
+
+				default: break;
+			}
+		}
+	}
+
+	if (CheckSavegameVersion(61)) {
+		/* Added the RoadType */
+		for (TileIndex t = 0; t < map_size; t++) {
+			switch(GetTileType(t)) {
+				case MP_STREET:
+					SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
+					switch (GetRoadTileType(t)) {
+						default: NOT_REACHED();
+						case ROAD_TILE_NORMAL:
+							SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
+							SB(_m[t].m4, 4, 4, 0);
+							SB(_m[t].m6, 2, 4, 0);
+							break;
+						case ROAD_TILE_CROSSING:
+							SB(_m[t].m4, 5, 2, GB(_m[t].m5, 2, 2));
+							break;
+						case ROAD_TILE_DEPOT:    break;
+					}
+					SetRoadTypes(t, ROADTYPES_ROAD);
+					break;
+
+				case MP_STATION:
+					if (IsRoadStop(t)) SetRoadTypes(t, ROADTYPES_ROAD);
+					break;
+
+				case MP_TUNNELBRIDGE:
+					if ((IsTunnel(t) ? GetTunnelTransportType(t) : GetBridgeTransportType(t)) == TRANSPORT_ROAD) {
+						SetRoadTypes(t, ROADTYPES_ROAD);
+					}
+					break;
+
+				default: break;
+			}
+		}
+	}
+
 	if (CheckSavegameVersion(42)) {
 		Vehicle* v;
 
@@ -1440,9 +1509,10 @@
 
 							MakeRoadNormal(
 								t,
-								GetTileOwner(t),
 								axis == AXIS_X ? ROAD_Y : ROAD_X,
-								town
+								ROADTYPES_ROAD,
+								town,
+								GetTileOwner(t), OWNER_NONE, OWNER_NONE
 							);
 						}
 					} else {
@@ -1490,34 +1560,6 @@
 		}
 	}
 
-	if (CheckSavegameVersion(48)) {
-		for (TileIndex t = 0; t < map_size; t++) {
-			switch (GetTileType(t)) {
-				case MP_RAILWAY:
-					if (IsPlainRailTile(t)) {
-						/* Swap ground type and signal type for plain rail tiles, so the
-						 * ground type uses the same bits as for depots and waypoints. */
-						uint tmp = GB(_m[t].m4, 0, 4);
-						SB(_m[t].m4, 0, 4, GB(_m[t].m2, 0, 4));
-						SB(_m[t].m2, 0, 4, tmp);
-					} else if (HASBIT(_m[t].m5, 2)) {
-						/* Split waypoint and depot rail type and remove the subtype. */
-						CLRBIT(_m[t].m5, 2);
-						CLRBIT(_m[t].m5, 6);
-					}
-					break;
-
-				case MP_STREET:
-					/* Swap m3 and m4, so the track type for rail crossings is the
-					 * same as for normal rail. */
-					Swap(_m[t].m3, _m[t].m4);
-					break;
-
-				default: break;
-			}
-		}
-	}
-
 	/* Elrails got added in rev 24 */
 	if (CheckSavegameVersion(24)) {
 		Vehicle *v;
@@ -1776,8 +1818,6 @@
 	 * space for newhouses grf features. A new byte, m7, was also added. */
 	if (CheckSavegameVersion(53)) {
 		for (TileIndex t = 0; t < map_size; t++) {
-			_me[t].m7 = 0;
-
 			if (IsTileType(t, MP_HOUSE)) {
 				if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
 					/* Move the construction stage from m3[7..6] to m5[5..4].
@@ -1943,6 +1983,10 @@
 					!(v->vehstatus & (VS_STOPPED | VS_CRASHED)) && // not stopped or crashed
 					v->current_order.type == OT_LOADING) {         // loading
 				GetStation(v->last_station_visited)->loading_vehicles.push_back(v);
+
+				/* The loading finished flag is *only* set when actually completely
+				 * finished. Because the vehicle is loading, it is not finished. */
+				CLRBIT(v->vehicle_flags, VF_LOADING_FINISHED);
 			}
 		}
 	}
@@ -1958,6 +2002,20 @@
 		_opt.diff.number_towns++;
 	}
 
+	/* Recalculate */
+	Group *g;
+	FOR_ALL_GROUPS(g) {
+		const Vehicle *v;
+		FOR_ALL_VEHICLES(v) {
+			if (!IsEngineCountable(v)) continue;
+
+			if (v->group_id != g->index || v->type != g->vehicle_type || v->owner != g->owner) continue;
+
+			g->num_engines[v->engine_type]++;
+		}
+	}
+
+
 	return true;
 }
 
--- a/src/openttd.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/openttd.h	Fri May 25 00:25:08 2007 +0000
@@ -40,6 +40,7 @@
 struct NewsItem;
 struct Industry;
 struct DrawPixelInfo;
+struct Group;
 typedef byte VehicleOrderID;  ///< The index of an order within its current vehicle (not pool related)
 typedef byte CargoID;
 typedef byte LandscapeID;
@@ -63,6 +64,7 @@
 typedef uint16 WaypointID;
 typedef uint16 OrderID;
 typedef uint16 SignID;
+typedef uint16 GroupID;
 typedef uint16 EngineRenewID;
 typedef uint16 DestinationID;
 
@@ -362,7 +364,8 @@
 typedef int32 ClearTileProc(TileIndex tile, byte flags);
 typedef void GetAcceptedCargoProc(TileIndex tile, AcceptedCargo res);
 typedef void GetTileDescProc(TileIndex tile, TileDesc *td);
-/* GetTileTrackStatusProcs return a value that contains the possible tracks
+/**
+ * GetTileTrackStatusProcs return a value that contains the possible tracks
  * that can be taken on a given tile by a given transport. The return value is
  * composed as follows: 0xaabbccdd. ccdd and aabb are bitmasks of trackdirs,
  * where bit n corresponds to trackdir n. ccdd are the trackdirs that are
@@ -380,8 +383,12 @@
  * are a track, the fourth bit is the direction. these give 12 (or 14)
  * possible options: 0-5 and 8-13, so we need 14 bits for a trackdir bitmask
  * above.
+ * @param tile     the tile to get the track status from
+ * @param mode     the mode of transportation
+ * @param sub_mode used to differentiate between different kinds within the mode
+ * @return the above mentions track status information
  */
-typedef uint32 GetTileTrackStatusProc(TileIndex tile, TransportType mode);
+typedef uint32 GetTileTrackStatusProc(TileIndex tile, TransportType mode, uint sub_mode);
 typedef void GetProducedCargoProc(TileIndex tile, CargoID *b);
 typedef void ClickTileProc(TileIndex tile);
 typedef void AnimateTileProc(TileIndex tile);
--- a/src/order_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/order_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -6,10 +6,10 @@
 #include "openttd.h"
 #include "order.h"
 #include "airport.h"
+#include "vehicle.h"
 #include "depot.h"
 #include "functions.h"
 #include "table/strings.h"
-#include "vehicle.h"
 #include "waypoint.h"
 #include "command.h"
 #include "station.h"
@@ -583,10 +583,12 @@
 
 		if (v->type == VEH_ROAD) ClearSlot(v);
 
-		/* NON-stop flag is misused to see if a train is in a station that is
-		 * on his order list or not */
-		if (v->current_order.type == OT_LOADING && HASBIT(v->current_order.flags, OFB_NON_STOP))
-			v->current_order.flags = 0;
+		if (v->current_order.type == OT_LOADING) {
+			v->LeaveStation();
+			/* NON-stop flag is misused to see if a train is in a station that is
+			 * on his order list or not */
+			if (HASBIT(v->current_order.flags, OFB_NON_STOP)) v->current_order.flags = 0;
+		}
 
 		InvalidateVehicleOrder(v);
 	}
--- a/src/pathfind.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/pathfind.cpp	Fri May 25 00:25:08 2007 +0000
@@ -153,7 +153,7 @@
 	if (++tpf->rd.cur_length > 50)
 		return;
 
-	bits = GetTileTrackStatus(tile, tpf->tracktype);
+	bits = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
 	bits = (byte)((bits | (bits >> 8)) & _bits_mask[direction]);
 	if (bits == 0)
 		return;
@@ -322,7 +322,7 @@
 
 	tpf->rd.cur_length++;
 
-	bits = GetTileTrackStatus(tile, tpf->tracktype);
+	bits = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
 
 	if ((byte)bits != tpf->var2) {
 		bits &= _tpfmode1_and[direction];
@@ -363,7 +363,7 @@
 	direction = ReverseDiagDir(direction);
 	tile += TileOffsByDiagDir(direction);
 
-	bits = GetTileTrackStatus(tile, tpf->tracktype);
+	bits = GetTileTrackStatus(tile, tpf->tracktype, tpf->sub_type);
 	bits |= (bits >> 8);
 
 	if ( (byte)bits != tpf->var2) {
@@ -388,7 +388,7 @@
 	} while (bits != 0);
 }
 
-void FollowTrack(TileIndex tile, uint16 flags, DiagDirection direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data)
+void FollowTrack(TileIndex tile, uint16 flags, uint sub_type, DiagDirection direction, TPFEnumProc *enum_proc, TPFAfterProc *after_proc, void *data)
 {
 	TrackPathFinder tpf;
 
@@ -411,6 +411,7 @@
 
 
 	tpf.tracktype = (TransportType)(flags & 0xFF);
+	tpf.sub_type = sub_type;
 
 	if (HASBIT(flags, 11)) {
 		tpf.rd.pft_var6 = 0xFF;
@@ -783,7 +784,7 @@
 			if (!IsTileType(tile, MP_RAILWAY) || !IsPlainRailTile(tile)) {
 				/* We found a tile which is not a normal railway tile.
 				 * Determine which tracks that exist on this tile. */
-				uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL) & _tpfmode1_and[direction];
+				uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _tpfmode1_and[direction];
 				bits = TrackdirBitsToTrackBits((TrackdirBits)(ts & TRACKDIR_BIT_MASK));
 
 				/* Check that the tile contains exactly one track */
--- a/src/pathfind.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/pathfind.h	Fri May 25 00:25:08 2007 +0000
@@ -57,6 +57,8 @@
 	TrackdirByte the_dir;
 
 	TransportTypeByte tracktype;
+	uint sub_type;
+
 	byte var2;
 	bool disable_tile_hash;
 	bool hasbit_13;
@@ -67,7 +69,7 @@
 	TrackPathFinderLink links[0x400]; ///< hopefully, this is enough.
 };
 
-void FollowTrack(TileIndex tile, uint16 flags, DiagDirection direction, TPFEnumProc* enum_proc, TPFAfterProc* after_proc, void* data);
+void FollowTrack(TileIndex tile, uint16 flags, uint sub_type, DiagDirection direction, TPFEnumProc* enum_proc, TPFAfterProc* after_proc, void* data);
 
 struct FindLengthOfTunnelResult {
 	TileIndex tile;
--- a/src/player.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/player.h	Fri May 25 00:25:08 2007 +0000
@@ -185,7 +185,7 @@
  * @return The engine type to replace with, or INVALID_ENGINE if no
  * replacement is in the list.
  */
-static inline EngineID EngineReplacementForPlayer(const Player *p, EngineID engine) { return EngineReplacement(p->engine_renew_list, engine); }
+static inline EngineID EngineReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacement(p->engine_renew_list, engine, group); }
 
 /**
  * Check if a player has a replacement set up for the given engine.
@@ -193,7 +193,7 @@
  * @param  engine Engine type to be replaced.
  * @return true if a replacement was set up, false otherwise.
  */
-static inline bool EngineHasReplacementForPlayer(const Player *p, EngineID engine) { return EngineReplacementForPlayer(p, engine) != INVALID_ENGINE; }
+static inline bool EngineHasReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacementForPlayer(p, engine, group) != INVALID_ENGINE; }
 
 /**
  * Add an engine replacement for the player.
@@ -203,7 +203,7 @@
  * @param flags The calling command flags.
  * @return 0 on success, CMD_ERROR on failure.
  */
-static inline int32 AddEngineReplacementForPlayer(Player *p, EngineID old_engine, EngineID new_engine, uint32 flags) { return AddEngineReplacement(&p->engine_renew_list, old_engine, new_engine, flags); }
+static inline int32 AddEngineReplacementForPlayer(Player *p, EngineID old_engine, EngineID new_engine, GroupID group, uint32 flags) { return AddEngineReplacement(&p->engine_renew_list, old_engine, new_engine, group, flags); }
 
 /**
  * Remove an engine replacement for the player.
@@ -212,7 +212,7 @@
  * @param flags The calling command flags.
  * @return 0 on success, CMD_ERROR on failure.
  */
-static inline int32 RemoveEngineReplacementForPlayer(Player *p, EngineID engine, uint32 flags) {return RemoveEngineReplacement(&p->engine_renew_list, engine, flags); }
+static inline int32 RemoveEngineReplacementForPlayer(Player *p, EngineID engine, GroupID group, uint32 flags) {return RemoveEngineReplacement(&p->engine_renew_list, engine, group, flags); }
 
 /**
  * Reset the livery schemes to the player's primary colour.
--- a/src/players.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/players.cpp	Fri May 25 00:25:08 2007 +0000
@@ -27,6 +27,7 @@
 #include "date.h"
 #include "window.h"
 #include "player_face.h"
+#include "group.h"
 
 /**
  * Sets the local player and updates the patch settings that are set on a
@@ -637,6 +638,7 @@
  * if p1 = 2, then
  * - p2 = minimum amount of money available
  * if p1 = 3, then:
+ * - p1 bits  8-15 = engine group
  * - p2 bits  0-15 = old engine type
  * - p2 bits 16-31 = new engine type
  * if p1 = 4, then:
@@ -692,8 +694,10 @@
 		case 3: {
 			EngineID old_engine_type = GB(p2, 0, 16);
 			EngineID new_engine_type = GB(p2, 16, 16);
+			GroupID id_g = GB(p1, 16, 16);
 			int32 cost;
 
+			if (!IsValidGroupID(id_g) && !IsDefaultGroupID(id_g)) return CMD_ERROR;
 			if (new_engine_type != INVALID_ENGINE) {
 				/* First we make sure that it's a valid type the user requested
 				 * check that it's an engine that is in the engine array */
@@ -713,9 +717,9 @@
 				if (!HASBIT(GetEngine(new_engine_type)->player_avail, _current_player))
 					return CMD_ERROR;
 
-				cost = AddEngineReplacementForPlayer(p, old_engine_type, new_engine_type, flags);
+				cost = AddEngineReplacementForPlayer(p, old_engine_type, new_engine_type, id_g, flags);
 			} else {
-				cost = RemoveEngineReplacementForPlayer(p, old_engine_type, flags);
+				cost = RemoveEngineReplacementForPlayer(p, old_engine_type,id_g, flags);
 			}
 
 			if (IsLocalPlayer()) InvalidateAutoreplaceWindow(old_engine_type);
@@ -900,6 +904,7 @@
 			p->is_active = false;
 		}
 		RemoveAllEngineReplacementForPlayer(p);
+		RemoveAllGroupsForPlayer(p);
 
 	} break;
 
--- a/src/rail_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/rail_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -295,10 +295,25 @@
 			if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
 				if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
 
-				if ((track == TRACK_X && GetRoadBits(tile) == ROAD_Y) ||
-						(track == TRACK_Y && GetRoadBits(tile) == ROAD_X)) {
+				RoadTypes roadtypes = GetRoadTypes(tile);
+				RoadBits road = GetRoadBits(tile, ROADTYPE_ROAD);
+				RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
+				switch (roadtypes) {
+					default: break;
+					case ROADTYPES_ROADTRAM: if (road == tram) break;
+						/* FALL THROUGH */
+					case ROADTYPES_ROADHWAY: // Road and highway are incompatible in this case
+					case ROADTYPES_TRAMHWAY: // Tram and highway are incompatible in this case
+					case ROADTYPES_ALL:      // Also incompatible
+						return CMD_ERROR;
+				}
+
+				road |= tram | GetRoadBits(tile, ROADTYPE_HWAY);
+
+				if ((track == TRACK_X && road == ROAD_Y) ||
+						(track == TRACK_Y && road == ROAD_X)) {
 					if (flags & DC_EXEC) {
-						MakeRoadCrossing(tile, GetTileOwner(tile), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, GetTownIndex(tile));
+						MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile));
 					}
 					break;
 				}
@@ -359,7 +374,7 @@
 			}
 
 			if (flags & DC_EXEC) {
-				MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
+				MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
 			}
 			break;
 		}
@@ -1700,7 +1715,7 @@
 		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
 		ssd.has_presignal = false;
 
-		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
+		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, 0, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
 		ChangeSignalStates(&ssd);
 
 		/* remember the result only for the first iteration. */
@@ -1892,7 +1907,7 @@
 }
 
 
-static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	if (mode != TRANSPORT_RAIL) return 0;
 
--- a/src/rail_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/rail_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -72,7 +72,7 @@
 
 static void PlaceRail_NE(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_FIX_Y);
+	VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_RAIL_NE);
 }
 
 static void PlaceRail_E(TileIndex tile)
@@ -83,12 +83,12 @@
 
 static void PlaceRail_NW(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_FIX_X);
+	VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_RAIL_NW);
 }
 
 static void PlaceRail_AutoRail(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_RAILDIRS);
+	VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL);
 }
 
 static void PlaceExtraDepotRail(TileIndex tile, uint16 extra)
@@ -151,13 +151,13 @@
 static void PlaceRail_Station(TileIndex tile)
 {
 	if (_remove_button_clicked) {
-		VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_RemoveFromStation);
+		VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_REMOVE_STATION);
 	} else if (_railstation.dragdrop) {
-		VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED);
+		VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION);
 		VpSetPlaceSizingLimit(_patches.station_spread);
 	} else {
 		DoCommandP(tile,
-				_railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16),
+				_railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16) | (_ctrl_pressed << 24),
 				_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
 				CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_AUTO | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
 	}
@@ -168,7 +168,7 @@
 	byte trackstat;
 	uint i;
 
-	trackstat = (byte)GetTileTrackStatus(tile, TRANSPORT_RAIL);
+	trackstat = (byte)GetTileTrackStatus(tile, TRANSPORT_RAIL, 0);
 
 	if (trackstat & TRACK_BIT_VERT) // N-S direction
 		trackstat = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT;
@@ -197,7 +197,7 @@
 
 static void PlaceRail_Bridge(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_OR_Y);
+	VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
 }
 
 void CcBuildRailTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
@@ -223,12 +223,12 @@
 
 static void PlaceRail_ConvertRail(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_ConvertRailArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CONVERT_RAIL);
 }
 
 static void PlaceRail_AutoSignals(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_SIGNALDIRS);
+	VpStartPlaceSizing(tile, VPM_SIGNALDIRS, DDSP_BUILD_SIGNALS);
 }
 
 
@@ -492,7 +492,7 @@
 		return;
 
 	case WE_PLACE_DRAG: {
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata & 0xF);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		return;
 	}
 
@@ -501,30 +501,44 @@
 			TileIndex start_tile = e->we.place.starttile;
 			TileIndex end_tile = e->we.place.tile;
 
-			if (e->we.place.userdata == VPM_X_OR_Y) {
-				ResetObjectToPlace();
-				ShowBuildBridgeWindow(start_tile, end_tile, _cur_railtype);
-			} else if (e->we.place.userdata == VPM_RAILDIRS) {
-				bool old = _remove_button_clicked;
-				if (_ctrl_pressed) _remove_button_clicked = true;
-				HandleAutodirPlacement();
-				_remove_button_clicked = old;
-			} else if (e->we.place.userdata == VPM_SIGNALDIRS) {
-				HandleAutoSignalPlacement();
-			} else if ((e->we.place.userdata & 0xF) == VPM_X_AND_Y) {
-				if (GUIPlaceProcDragXY(e)) break;
+			switch (e->we.place.select_proc) {
+				case DDSP_BUILD_BRIDGE:
+					ResetObjectToPlace();
+					ShowBuildBridgeWindow(start_tile, end_tile, _cur_railtype);
+					break;
 
-				if ((e->we.place.userdata >> 4) == GUI_PlaceProc_RemoveFromStation >> 4) {
-					DoCommandP(end_tile, start_tile, 0, CcPlaySound1E, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION));
+				case DDSP_PLACE_AUTORAIL: {
+					bool old = _remove_button_clicked;
+					if (_ctrl_pressed) _remove_button_clicked = true;
+					HandleAutodirPlacement();
+					_remove_button_clicked = old;
+					break;
 				}
 
-				if ((e->we.place.userdata >> 4) == GUI_PlaceProc_ConvertRailArea >> 4) {
+				case DDSP_BUILD_SIGNALS:
+					HandleAutoSignalPlacement();
+					break;
+
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(e);
+					break;
+
+				case DDSP_REMOVE_STATION:
+					DoCommandP(end_tile, start_tile, 0, CcPlaySound1E, CMD_REMOVE_FROM_RAILROAD_STATION | CMD_MSG(STR_CANT_REMOVE_PART_OF_STATION));
+					break;
+
+				case DDSP_CONVERT_RAIL:
 					DoCommandP(end_tile, start_tile, _cur_railtype, CcPlaySound10, CMD_CONVERT_RAIL | CMD_MSG(STR_CANT_CONVERT_RAIL));
-				}
-			} else if (e->we.place.userdata == VPM_X_AND_Y_LIMITED) {
-				HandleStationPlacement(start_tile, end_tile);
-			} else {
-				DoRailroadTrack(e->we.place.userdata & 1);
+					break;
+
+				case DDSP_BUILD_STATION:
+					HandleStationPlacement(start_tile, end_tile);
+					break;
+
+				case DDSP_PLACE_RAIL_NE:
+				case DDSP_PLACE_RAIL_NW:
+					DoRailroadTrack(e->we.place.select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y);
+					break;
 			}
 		}
 		break;
@@ -651,7 +665,7 @@
 	if (!_railstation.orientation) Swap(w, h);
 
 	DoCommandP(TileXY(sx, sy),
-			_railstation.orientation | (w << 8) | (h << 16),
+			_railstation.orientation | (w << 8) | (h << 16) | (_ctrl_pressed << 24),
 			_cur_railtype | (_railstation.station_class << 8) | (_railstation.station_type << 16), CcStation,
 			CMD_BUILD_RAILROAD_STATION | CMD_NO_WATER | CMD_AUTO | CMD_MSG(STR_100F_CAN_T_BUILD_RAILROAD_STATION));
 }
@@ -741,7 +755,7 @@
 			old_dpi = _cur_dpi;
 			_cur_dpi = &tmp_dpi;
 			if (!DrawStationTile(32, 16, _cur_railtype, AXIS_X, _railstation.station_class, _railstation.station_type)) {
-				StationPickerDrawSprite(32, 16, _cur_railtype, 2);
+				StationPickerDrawSprite(32, 16, _cur_railtype, INVALID_ROADTYPE, 2);
 			}
 			_cur_dpi = old_dpi;
 		}
@@ -751,7 +765,7 @@
 			old_dpi = _cur_dpi;
 			_cur_dpi = &tmp_dpi;
 			if (!DrawStationTile(32, 16, _cur_railtype, AXIS_Y, _railstation.station_class, _railstation.station_type)) {
-				StationPickerDrawSprite(32, 16, _cur_railtype, 3);
+				StationPickerDrawSprite(32, 16, _cur_railtype, INVALID_ROADTYPE, 3);
 			}
 			_cur_dpi = old_dpi;
 		}
--- a/src/road.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/road.h	Fri May 25 00:25:08 2007 +0000
@@ -7,6 +7,68 @@
 
 #include "helpers.hpp"
 
+/**
+ * The different roadtypes we support
+ * @note currently only ROADTYPE_ROAD is supported.
+ */
+enum RoadType {
+	ROADTYPE_ROAD = 0,
+	ROADTYPE_TRAM = 1,
+	ROADTYPE_HWAY = 2, ///< Only a placeholder. Not sure what we are going to do with this road type.
+	ROADTYPE_END,
+	INVALID_ROADTYPE = 0xFF
+};
+DECLARE_POSTFIX_INCREMENT(RoadType);
+
+/**
+ * The different roadtypes we support, but then a bitmask of them
+ * @note currently only ROADTYPES_ROAD is supported.
+ */
+enum RoadTypes {
+	ROADTYPES_NONE     = 0,
+	ROADTYPES_ROAD     = 1 << ROADTYPE_ROAD,
+	ROADTYPES_TRAM     = 1 << ROADTYPE_TRAM,
+	ROADTYPES_HWAY     = 1 << ROADTYPE_HWAY,
+	ROADTYPES_ROADTRAM = ROADTYPES_ROAD | ROADTYPES_TRAM,
+	ROADTYPES_ROADHWAY = ROADTYPES_ROAD | ROADTYPES_HWAY,
+	ROADTYPES_TRAMHWAY = ROADTYPES_TRAM | ROADTYPES_HWAY,
+	ROADTYPES_ALL      = ROADTYPES_ROAD | ROADTYPES_TRAM | ROADTYPES_HWAY,
+};
+DECLARE_ENUM_AS_BIT_SET(RoadTypes);
+
+/**
+ * Whether the given roadtype is valid.
+ * @param rt the roadtype to check for validness
+ * @return true if and only if valid
+ */
+static inline bool IsValidRoadType(RoadType rt)
+{
+	return rt == ROADTYPE_ROAD;
+}
+
+/**
+ * Are the given bits pointing to valid roadtypes?
+ * @param rts the roadtypes to check for validness
+ * @return true if and only if valid
+ */
+static inline bool AreValidRoadTypes(RoadTypes rts)
+{
+	return rts == ROADTYPES_ROAD;
+}
+
+/**
+ * Maps a RoadType to the corresponding RoadTypes value
+ */
+static inline RoadTypes RoadTypeToRoadTypes(RoadType rt)
+{
+	return (RoadTypes)(1 << rt);
+}
+
+static inline RoadTypes ComplementRoadTypes(RoadTypes r)
+{
+	return (RoadTypes)(ROADTYPES_ALL ^ r);
+}
+
 enum RoadBits {
 	ROAD_NONE = 0U,
 	ROAD_NW  = 1U,
@@ -48,8 +110,9 @@
  * @param remove    the roadbits that are going to be removed
  * @param owner     the actual owner of the roadbits of the tile
  * @param edge_road are the removed bits from a town?
+ * @param rt        the road type to remove the bits from
  * @return true when it is allowed to remove the road bits
  */
-bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road);
+bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt);
 
 #endif /* ROAD_H */
--- a/src/road_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/road_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -27,6 +27,8 @@
 #include "yapf/yapf.h"
 #include "depot.h"
 #include "newgrf.h"
+#include "station_map.h"
+#include "tunnel_map.h"
 
 
 static uint CountRoadBits(RoadBits r)
@@ -41,13 +43,13 @@
 }
 
 
-bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road)
+bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
 {
 	RoadBits present;
 	RoadBits n;
 	*edge_road = true;
 
-	if (_game_mode == GM_EDITOR) return true;
+	if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
 
 	/* Only do the special processing for actual players. */
 	if (!IsValidPlayer(_current_player)) return true;
@@ -60,11 +62,11 @@
 
 	/* Get a bitmask of which neighbouring roads has a tile */
 	n = ROAD_NONE;
-	present = GetAnyRoadBits(tile);
-	if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0)) & ROAD_SW) n |= ROAD_NE;
-	if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1)) & ROAD_NW) n |= ROAD_SE;
-	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0)) & ROAD_NE) n |= ROAD_SW;
-	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1)) & ROAD_SE) n |= ROAD_NW;
+	present = GetAnyRoadBits(tile, rt);
+	if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1,  0), rt) & ROAD_SW) n |= ROAD_NE;
+	if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile,  0,  1), rt) & ROAD_NW) n |= ROAD_SE;
+	if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile,  1,  0), rt) & ROAD_NE) n |= ROAD_SW;
+	if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile,  0, -1), rt) & ROAD_SE) n |= ROAD_NW;
 
 	/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
 	 * then allow it */
@@ -84,15 +86,16 @@
 	return true;
 }
 
-static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road)
+static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
 {
-	return CheckAllowRemoveRoad(tile, remove, IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile), edge_road);
+	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
 }
 
 /** Delete a piece of road.
  * @param tile tile where to remove road from
  * @param flags operation to perform
  * @param p1 bit 0..3 road pieces to remove (RoadBits)
+ *           bit 4..5 road type
  * @param p2 unused
  */
 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@@ -100,7 +103,6 @@
 	/* cost for removing inner/edge -roads */
 	static const uint16 road_remove_cost[2] = {50, 18};
 
-	Owner owner;
 	Town *t;
 	/* true if the roadpiece was always removeable,
 	 * false if it was a center piece. Affects town ratings drop */
@@ -108,9 +110,29 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
-	if (!IsTileType(tile, MP_STREET)) return CMD_ERROR;
+	RoadType rt = (RoadType)GB(p1, 4, 2);
+	if (!IsValidRoadType(rt)) return CMD_ERROR;
 
-	owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile);
+	Owner owner;
+	switch (GetTileType(tile)) {
+		case MP_STREET:
+			owner = GetRoadOwner(tile, rt);
+			break;
+
+		case MP_STATION:
+			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
+			owner = GetTileOwner(tile);
+			break;
+
+		case MP_TUNNELBRIDGE:
+			if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) ||
+					(IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR;
+			owner = GetTileOwner(tile);
+			break;
+
+		default:
+			return CMD_ERROR;
+	}
 
 	if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
 		t = GetTownByTile(tile);
@@ -119,8 +141,11 @@
 	}
 
 	RoadBits pieces = Extract<RoadBits, 0>(p1);
+	RoadTypes rts = GetRoadTypes(tile);
+	/* The tile doesn't have the given road type */
+	if (!HASBIT(rts, rt)) return CMD_ERROR;
 
-	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road)) return CMD_ERROR;
+	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
 
 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
@@ -128,9 +153,40 @@
 	 * removal allowance depends on difficulty setting */
 	if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR;
 
+	if (!IsTileType(tile, MP_STREET)) {
+		/* If it's the last roadtype, just clear the whole tile */
+		if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+
+		int32 cost;
+		if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+			TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
+			/* Pay for *every* tile of the bridge or tunnel */
+			cost = (DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road;
+			if (flags & DC_EXEC) {
+				SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
+				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
+
+				/* Mark tiles diry that have been repaved */
+				MarkTileDirtyByTile(other_end);
+				if (IsBridge(tile)) {
+					TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
+
+					for (TileIndex t = tile; tile != other_end; tile += delta) MarkTileDirtyByTile(t);
+				}
+			}
+		} else {
+			cost = _price.remove_road;
+			if (flags & DC_EXEC) {
+				SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
+				MarkTileDirtyByTile(tile);
+			}
+		}
+		return cost;
+	}
+
 	switch (GetRoadTileType(tile)) {
 		case ROAD_TILE_NORMAL: {
-			RoadBits present = GetRoadBits(tile);
+			RoadBits present = GetRoadBits(tile, rt);
 			RoadBits c = pieces;
 
 			if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
@@ -143,16 +199,22 @@
 
 			/* limit the bits to delete to the existing bits. */
 			c &= present;
-			if (c == 0) return CMD_ERROR;
+			if (c == ROAD_NONE) return CMD_ERROR;
 
 			if (flags & DC_EXEC) {
 				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
 
 				present ^= c;
-				if (present == 0) {
-					DoClearSquare(tile);
+				if (present == ROAD_NONE) {
+					RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
+					if (rts == ROADTYPES_NONE) {
+						DoClearSquare(tile);
+					} else {
+						SetRoadBits(tile, ROAD_NONE, rt);
+						SetRoadTypes(tile, rts);
+					}
 				} else {
-					SetRoadBits(tile, present);
+					SetRoadBits(tile, present, rt);
 					MarkTileDirtyByTile(tile);
 				}
 			}
@@ -165,9 +227,16 @@
 			}
 
 			if (flags & DC_EXEC) {
-				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+				if (rt == ROADTYPE_ROAD) {
+					ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
+				}
 
-				MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
+				RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
+				if (rts == ROADTYPES_NONE) {
+					MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
+				} else {
+					SetRoadTypes(tile, rts);
+				}
 				MarkTileDirtyByTile(tile);
 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
 			}
@@ -255,6 +324,7 @@
  * @param tile tile where to build road
  * @param flags operation to perform
  * @param p1 bit 0..3 road pieces to build (RoadBits)
+ *           bit 4..5 road type
  * @param p2 the town that is building the road (0 if not applicable)
  */
 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@@ -272,6 +342,9 @@
 
 	RoadBits pieces = Extract<RoadBits, 0>(p1);
 
+	RoadType rt = (RoadType)GB(p1, 4, 2);
+	if (!IsValidRoadType(rt)) return CMD_ERROR;
+
 	tileh = GetTileSlope(tile, NULL);
 
 	switch (GetTileType(tile)) {
@@ -279,8 +352,9 @@
 			switch (GetRoadTileType(tile)) {
 				case ROAD_TILE_NORMAL:
 					if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
+					if (!HASBIT(GetRoadTypes(tile), rt)) break;
 
-					existing = GetRoadBits(tile);
+					existing = GetRoadBits(tile, rt);
 					if ((existing & pieces) == pieces) {
 						return_cmd_error(STR_1007_ALREADY_BUILT);
 					}
@@ -288,10 +362,9 @@
 					break;
 
 				case ROAD_TILE_CROSSING:
-					if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct?
-						return_cmd_error(STR_1007_ALREADY_BUILT);
-					}
-					goto do_clear;
+					if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
+					if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) goto do_clear;
+					break;
 
 				default:
 				case ROAD_TILE_DEPOT:
@@ -332,12 +405,23 @@
 
 			if (flags & DC_EXEC) {
 				YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
-				MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2);
+				MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt), p2);
 				MarkTileDirtyByTile(tile);
 			}
 			return _price.build_road * 2;
 		}
 
+		case MP_STATION:
+			if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
+			if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
+			break;
+
+		case MP_TUNNELBRIDGE:
+			if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) ||
+					(IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR;
+			if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
+			break;
+
 		default:
 do_clear:;
 			ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
@@ -359,12 +443,44 @@
 	}
 
 	cost += CountRoadBits(pieces) * _price.build_road;
+	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
+		/* Pay for *every* tile of the bridge or tunnel */
+		cost *= DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile);
+	}
 
 	if (flags & DC_EXEC) {
-		if (IsTileType(tile, MP_STREET)) {
-			SetRoadBits(tile, existing | pieces);
-		} else {
-			MakeRoadNormal(tile, _current_player, pieces, p2);
+		switch (GetTileType(tile)) {
+			case MP_STREET: {
+				RoadTileType rtt = GetRoadTileType(tile);
+				if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) {
+					SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
+					SetRoadOwner(tile, rt, _current_player);
+				}
+				if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt);
+			} break;
+
+			case MP_TUNNELBRIDGE: {
+				TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
+
+				SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt));
+				SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
+
+				/* Mark tiles diry that have been repaved */
+				MarkTileDirtyByTile(other_end);
+				if (IsBridge(tile)) {
+					TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
+
+					for (TileIndex t = tile + delta; tile != other_end; tile += delta) MarkTileDirtyByTile(t);
+				}
+			} break;
+
+			case MP_STATION:
+				SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
+				break;
+
+			default:
+				MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player);
+				break;
 		}
 
 		MarkTileDirtyByTile(tile);
@@ -411,6 +527,7 @@
  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
+ * - p2 = (bit 3 + 4) - road type
  */
 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -422,6 +539,8 @@
 	if (p1 >= MapSize()) return CMD_ERROR;
 
 	start_tile = p1;
+	RoadType rt = (RoadType)GB(p2, 3, 2);
+	if (!IsValidRoadType(rt)) return CMD_ERROR;
 
 	/* Only drag in X or Y direction dictated by the direction variable */
 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
@@ -444,7 +563,7 @@
 		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
 		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
 
-		ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD);
+		ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
 		if (CmdFailed(ret)) {
 			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
 			_error_message = INVALID_STRING_ID;
@@ -468,6 +587,7 @@
  * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
  * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
  * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
+ * - p2 = (bit 3 + 4) - road type
  */
 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -479,6 +599,8 @@
 	if (p1 >= MapSize()) return CMD_ERROR;
 
 	start_tile = p1;
+	RoadType rt = (RoadType)GB(p2, 3, 2);
+	if (!IsValidRoadType(rt)) return CMD_ERROR;
 
 	/* Only drag in X or Y direction dictated by the direction variable */
 	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
@@ -503,7 +625,7 @@
 
 		/* try to remove the halves. */
 		if (bits != 0) {
-			ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD);
+			ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
 			if (!CmdFailed(ret)) cost += ret;
 		}
 
@@ -519,6 +641,7 @@
  * @param tile tile where to build the depot
  * @param flags operation to perform
  * @param p1 bit 0..1 entrance direction (DiagDirection)
+ *           bit 2..3 road type
  * @param p2 unused
  *
  * @todo When checking for the tile slope,
@@ -533,6 +656,9 @@
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
 	DiagDirection dir = Extract<DiagDirection, 0>(p1);
+	RoadType rt = (RoadType)GB(p1, 2, 2);
+
+	if (!IsValidRoadType(rt)) return CMD_ERROR;
 
 	tileh = GetTileSlope(tile, NULL);
 	if (tileh != SLOPE_FLAT && (
@@ -555,7 +681,7 @@
 		dep->xy = tile;
 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 
-		MakeRoadDepot(tile, _current_player, dir);
+		MakeRoadDepot(tile, _current_player, dir, rt);
 		MarkTileDirtyByTile(tile);
 	}
 	return cost + _price.build_road_depot;
@@ -577,13 +703,22 @@
 {
 	switch (GetRoadTileType(tile)) {
 		case ROAD_TILE_NORMAL: {
-			RoadBits b = GetRoadBits(tile);
+			RoadBits b = GetAllRoadBits(tile);
 
 #define M(x) (1 << (x))
 			/* Clear the road if only one piece is on the tile OR the AI tries
 			 * to clear town road OR we are not using the DC_AUTO flag */
 			if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || !(flags & DC_AUTO)) {
-				return DoCommand(tile, b, 0, flags, CMD_REMOVE_ROAD);
+				RoadTypes rts = GetRoadTypes(tile);
+				int32 ret = 0;
+				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
+					if (HASBIT(rts, rt)) {
+						int32 tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
+						if (CmdFailed(tmp_ret)) return tmp_ret;
+						ret += rt;
+					}
+				}
+				return ret;
 			}
 			return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
 		}
@@ -682,7 +817,7 @@
  */
 static void DrawRoadBits(TileInfo* ti)
 {
-	RoadBits road = GetRoadBits(ti->tile);
+	RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
 	const DrawRoadTileStruct *drts;
 	SpriteID image = 0;
 	SpriteID pal = PAL_NONE;
@@ -722,7 +857,7 @@
 	}
 
 	/* Return if full detail is disabled, or we are zoomed fully out. */
-	if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom == 2) return;
+	if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
 
 	/* Draw extra details. */
 	for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) {
@@ -807,7 +942,7 @@
 	DrawBridgeMiddle(ti);
 }
 
-void DrawRoadDepotSprite(int x, int y, DiagDirection dir)
+void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
 {
 	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
 	const DrawTileSprites* dts =  &_road_depot[dir];
@@ -833,7 +968,7 @@
 
 	if (tileh == SLOPE_FLAT) return z;
 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
-		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
+		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
 
 		if (f != 0) {
 			if (IsSteepSlope(tileh)) {
@@ -853,7 +988,7 @@
 {
 	if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
 	if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
-		uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
+		uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
 
 		if (f == 0) return tileh;
 		if (f < 15) return SLOPE_FLAT; // leveled foundation
@@ -921,7 +1056,7 @@
 			/* Show an animation to indicate road work */
 			if (t->road_build_months != 0 &&
 					(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
-					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetRoadBits(tile) == ROAD_X || GetRoadBits(tile) == ROAD_Y)) {
+					GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) {
 				if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
 					StartRoadWorks(tile);
 
@@ -973,17 +1108,21 @@
 	0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F,
 };
 
-static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode, uint sub_mode)
 {
+
 	switch (mode) {
 		case TRANSPORT_RAIL:
 			if (!IsLevelCrossing(tile)) return 0;
 			return GetCrossingRailBits(tile) * 0x101;
 
 		case TRANSPORT_ROAD:
+			if ((GetRoadTypes(tile) & sub_mode) == 0) return 0;
 			switch (GetRoadTileType(tile)) {
-				case ROAD_TILE_NORMAL:
-					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile)] * 0x101;
+				case ROAD_TILE_NORMAL: {
+					RoadType rt = (RoadType)FindFirstBit(sub_mode);
+					return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile, rt)] * 0x101;
+				}
 
 				case ROAD_TILE_CROSSING: {
 					uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
@@ -1057,29 +1196,25 @@
 
 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
 {
-	if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) {
-		SetCrossingRoadOwner(tile, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
+	if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) {
+		DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
+		return;
 	}
 
-	if (!IsTileOwner(tile, old_player)) return;
+	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
+		if (!HASBIT(GetRoadTypes(tile), rt)) continue;
 
-	if (new_player != PLAYER_SPECTATOR) {
-		SetTileOwner(tile, new_player);
-	} else {
-		switch (GetRoadTileType(tile)) {
-			case ROAD_TILE_NORMAL:
-				SetTileOwner(tile, OWNER_NONE);
-				break;
+		if (GetRoadOwner(tile, rt) == old_player) {
+			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
 
-			case ROAD_TILE_CROSSING:
-				MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
-				break;
+			if (rt == ROADTYPE_TRAM) {
+				DoCommand(tile, ROADTYPE_TRAM << 4 | GetRoadBits(tile, ROADTYPE_ROAD), 0, DC_EXEC, CMD_REMOVE_ROAD);
+			}
+		}
+	}
 
-			default:
-			case ROAD_TILE_DEPOT:
-				DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
-				break;
-		}
+	if (IsLevelCrossing(tile)) {
+		MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
 	}
 }
 
--- a/src/road_cmd.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/road_cmd.h	Fri May 25 00:25:08 2007 +0000
@@ -7,6 +7,6 @@
 
 #include "direction.h"
 
-void DrawRoadDepotSprite(int x, int y, DiagDirection dir);
+void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt);
 
 #endif /* ROAD_CMD_H */
--- a/src/road_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/road_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -4,8 +4,6 @@
 
 #include "stdafx.h"
 #include "openttd.h"
-#include "road_cmd.h"
-#include "road_map.h"
 #include "table/sprites.h"
 #include "table/strings.h"
 #include "functions.h"
@@ -18,6 +16,9 @@
 #include "sound.h"
 #include "command.h"
 #include "variables.h"
+#include "road.h"
+#include "road_cmd.h"
+#include "road_map.h"
 #include "station_map.h"
 //needed for catchments
 #include "station.h"
@@ -31,6 +32,8 @@
 
 static byte _place_road_flag;
 
+static RoadType _cur_roadtype;
+
 static DiagDirection _road_depot_orientation;
 static DiagDirection _road_station_picker_orientation;
 
@@ -42,18 +45,18 @@
 static void PlaceRoad_NE(TileIndex tile)
 {
 	_place_road_flag = (_tile_fract_coords.y >= 8) + 4;
-	VpStartPlaceSizing(tile, VPM_FIX_X);
+	VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_NE);
 }
 
 static void PlaceRoad_NW(TileIndex tile)
 {
 	_place_road_flag = (_tile_fract_coords.x >= 8) + 0;
-	VpStartPlaceSizing(tile, VPM_FIX_Y);
+	VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_NW);
 }
 
 static void PlaceRoad_Bridge(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_OR_Y);
+	VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE);
 }
 
 
@@ -67,9 +70,35 @@
 	}
 }
 
+/** Structure holding information per roadtype for several functions */
+struct RoadTypeInfo {
+	StringID err_build_road;        ///< Building a normal piece of road
+	StringID err_remove_road;       ///< Removing a normal piece of road
+	StringID err_depot;             ///< Building a depot
+	StringID err_build_station[2];  ///< Building a bus or truck station
+	StringID err_remove_station[2]; ///< Removing of a bus or truck station
+
+	SpriteID cursor_nesw;           ///< Cursor for building NE and SW bits
+	SpriteID cursor_nwse;           ///< Cursor for building NW and SE bits
+};
+
+/** What errors/cursors must be shown for several types of roads */
+static const RoadTypeInfo _road_type_infos[] = {
+	{
+		STR_1804_CAN_T_BUILD_ROAD_HERE,
+		STR_1805_CAN_T_REMOVE_ROAD_FROM,
+		STR_1807_CAN_T_BUILD_ROAD_VEHICLE,
+		{ STR_1808_CAN_T_BUILD_BUS_STATION, STR_1809_CAN_T_BUILD_TRUCK_STATION },
+		{ STR_CAN_T_REMOVE_BUS_STATION,     STR_CAN_T_REMOVE_TRUCK_STATION     },
+
+		SPR_CURSOR_ROAD_NESW,
+		SPR_CURSOR_ROAD_NWSE,
+	},
+};
+
 static void PlaceRoad_Tunnel(TileIndex tile)
 {
-	DoCommandP(tile, 0x200, 0, CcBuildRoadTunnel, CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
+	DoCommandP(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, CcBuildRoadTunnel, CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
 }
 
 static void BuildRoadOutsideStation(TileIndex tile, DiagDirection direction)
@@ -77,24 +106,27 @@
 	tile += TileOffsByDiagDir(direction);
 	// if there is a roadpiece just outside of the station entrance, build a connecting route
 	if (IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
-		DoCommandP(tile, DiagDirToRoadBits(ReverseDiagDir(direction)), 0, NULL, CMD_BUILD_ROAD);
+		if (GetRoadBits(tile, _cur_roadtype) != ROAD_NONE) {
+			DoCommandP(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, NULL, CMD_BUILD_ROAD);
+		}
 	}
 }
 
 void CcRoadDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
 	if (success) {
+		DiagDirection dir = (DiagDirection)GB(p1, 0, 2);
 		SndPlayTileFx(SND_1F_SPLAT, tile);
 		ResetObjectToPlace();
-		BuildRoadOutsideStation(tile, (DiagDirection)p1);
+		BuildRoadOutsideStation(tile, dir);
 		/* For a drive-through road stop build connecting road for other entrance */
-		if (HASBIT(p2, 1)) BuildRoadOutsideStation(tile, ReverseDiagDir((DiagDirection)p1));
+		if (HASBIT(p2, 1)) BuildRoadOutsideStation(tile, ReverseDiagDir(dir));
 	}
 }
 
 static void PlaceRoad_Depot(TileIndex tile)
 {
-	DoCommandP(tile, _road_depot_orientation, 0, CcRoadDepot, CMD_BUILD_ROAD_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1807_CAN_T_BUILD_ROAD_VEHICLE));
+	DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0, CcRoadDepot, CMD_BUILD_ROAD_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot));
 }
 
 static void PlaceRoadStop(TileIndex tile, uint32 p2, uint32 cmd)
@@ -111,24 +143,24 @@
 static void PlaceRoad_BusStation(TileIndex tile)
 {
 	if (_remove_button_clicked) {
-		DoCommandP(tile, 0, RoadStop::BUS, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_BUS_STATION));
+		DoCommandP(tile, 0, RoadStop::BUS, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[RoadStop::BUS]));
 	} else {
-		PlaceRoadStop(tile, RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION));
+		PlaceRoadStop(tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[RoadStop::BUS]));
 	}
 }
 
 static void PlaceRoad_TruckStation(TileIndex tile)
 {
 	if (_remove_button_clicked) {
-		DoCommandP(tile, 0, RoadStop::TRUCK, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_TRUCK_STATION));
+		DoCommandP(tile, 0, RoadStop::TRUCK, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[RoadStop::TRUCK]));
 	} else {
-		PlaceRoadStop(tile, RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION));
+		PlaceRoadStop(tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[RoadStop::TRUCK]));
 	}
 }
 
 static void PlaceRoad_DemolishArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, 4);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
 }
 
 
@@ -149,12 +181,12 @@
 
 static void BuildRoadClick_NE(Window *w)
 {
-	HandlePlacePushButton(w, RTW_ROAD_X, SPR_CURSOR_ROAD_NESW, 1, PlaceRoad_NE);
+	HandlePlacePushButton(w, RTW_ROAD_X, _road_type_infos[_cur_roadtype].cursor_nesw, 1, PlaceRoad_NE);
 }
 
 static void BuildRoadClick_NW(Window *w)
 {
-	HandlePlacePushButton(w, RTW_ROAD_Y, SPR_CURSOR_ROAD_NWSE, 1, PlaceRoad_NW);
+	HandlePlacePushButton(w, RTW_ROAD_Y, _road_type_infos[_cur_roadtype].cursor_nwse, 1, PlaceRoad_NW);
 }
 
 
@@ -264,47 +296,42 @@
 		if (w != NULL) WP(w, def_d).close = true;
 		break;
 
-	case WE_PLACE_DRAG: {
-		int sel_method;
-		switch (e->we.place.userdata) {
-			case 1:
-				sel_method = VPM_FIX_X;
+	case WE_PLACE_DRAG:
+		switch (e->we.place.select_proc) {
+			case DDSP_PLACE_ROAD_NE:
 				_place_road_flag = (_place_road_flag & ~2) | ((e->we.place.pt.y & 8) >> 2);
 				break;
 
-			case 2:
-				sel_method = VPM_FIX_Y;
+			case DDSP_PLACE_ROAD_NW:
 				_place_road_flag = (_place_road_flag & ~2) | ((e->we.place.pt.x & 8) >> 2);
 				break;
-
-			case 4:
-				sel_method = VPM_X_AND_Y;
-				break;
-
-			default:
-				sel_method = VPM_X_OR_Y;
-				break;
 		}
 
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, sel_method);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		return;
-	}
 
 	case WE_PLACE_MOUSEUP:
 		if (e->we.place.pt.x != -1) {
 			TileIndex start_tile = e->we.place.starttile;
 			TileIndex end_tile = e->we.place.tile;
 
-			if (e->we.place.userdata == 0) {
-				ResetObjectToPlace();
-				ShowBuildBridgeWindow(start_tile, end_tile, 0x80);
-			} else if (e->we.place.userdata != 4) {
-				DoCommandP(end_tile, start_tile, _place_road_flag, CcPlaySound1D,
-					_remove_button_clicked ?
-					CMD_REMOVE_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1805_CAN_T_REMOVE_ROAD_FROM) :
-					CMD_BUILD_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1804_CAN_T_BUILD_ROAD_HERE));
-			} else {
-				DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
+			switch (e->we.place.select_proc) {
+				case DDSP_BUILD_BRIDGE:
+					ResetObjectToPlace();
+					ShowBuildBridgeWindow(start_tile, end_tile, 0x80 | RoadTypeToRoadTypes(_cur_roadtype));
+					break;
+
+				case DDSP_DEMOLISH_AREA:
+					DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
+					break;
+
+				case DDSP_PLACE_ROAD_NE:
+				case DDSP_PLACE_ROAD_NW:
+					DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3), CcPlaySound1D,
+						_remove_button_clicked ?
+						CMD_REMOVE_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
+						CMD_BUILD_LONG_ROAD | CMD_AUTO | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road));
+					break;
 			}
 		}
 		break;
@@ -312,7 +339,7 @@
 	case WE_PLACE_PRESIZE: {
 		TileIndex tile = e->we.place.tile;
 
-		DoCommand(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL);
+		DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL);
 		VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
 		break;
 	}
@@ -348,9 +375,10 @@
 	BuildRoadToolbWndProc
 };
 
-void ShowBuildRoadToolbar()
+void ShowBuildRoadToolbar(RoadType roadtype)
 {
 	if (!IsValidPlayer(_current_player)) return;
+	_cur_roadtype = roadtype;
 
 	DeleteWindowById(WC_BUILD_TOOLBAR, 0);
 	Window *w = AllocateWindowDesc(&_build_road_desc);
@@ -395,10 +423,10 @@
 	case WE_PAINT:
 		DrawWindowWidgets(w);
 
-		DrawRoadDepotSprite(70, 17, DIAGDIR_NE);
-		DrawRoadDepotSprite(70, 69, DIAGDIR_SE);
-		DrawRoadDepotSprite( 2, 69, DIAGDIR_SW);
-		DrawRoadDepotSprite( 2, 17, DIAGDIR_NW);
+		DrawRoadDepotSprite(70, 17, DIAGDIR_NE, _cur_roadtype);
+		DrawRoadDepotSprite(70, 69, DIAGDIR_SE, _cur_roadtype);
+		DrawRoadDepotSprite( 2, 69, DIAGDIR_SW, _cur_roadtype);
+		DrawRoadDepotSprite( 2, 17, DIAGDIR_NW, _cur_roadtype);
 		break;
 
 	case WE_CLICK: {
@@ -451,6 +479,12 @@
 {
 	switch (e->event) {
 	case WE_CREATE:
+		/* Trams don't have non-drivethrough stations */
+		if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
+			_road_station_picker_orientation = DIAGDIR_END;
+		}
+		SetWindowWidgetsDisabledState(w, _cur_roadtype == ROADTYPE_TRAM, 3, 4, 5, 6, WIDGET_LIST_END);
+
 		LowerWindowWidget(w, _road_station_picker_orientation + 3);
 		LowerWindowWidget(w, _station_show_coverage + 9);
 		break;
@@ -471,15 +505,15 @@
 
 		image = (w->window_class == WC_BUS_STATION) ? GFX_BUS_BASE : GFX_TRUCK_BASE;
 
-		StationPickerDrawSprite(103, 35, RAILTYPE_BEGIN, image);
-		StationPickerDrawSprite(103, 85, RAILTYPE_BEGIN, image + 1);
-		StationPickerDrawSprite(35, 85, RAILTYPE_BEGIN, image + 2);
-		StationPickerDrawSprite(35, 35, RAILTYPE_BEGIN, image + 3);
+		StationPickerDrawSprite(103, 35, RAILTYPE_BEGIN, ROADTYPE_ROAD, image);
+		StationPickerDrawSprite(103, 85, RAILTYPE_BEGIN, ROADTYPE_ROAD, image + 1);
+		StationPickerDrawSprite(35, 85, RAILTYPE_BEGIN, ROADTYPE_ROAD, image + 2);
+		StationPickerDrawSprite(35, 35, RAILTYPE_BEGIN, ROADTYPE_ROAD, image + 3);
 
 		image = (w->window_class == WC_BUS_STATION) ? GFX_BUS_BASE_EXT : GFX_TRUCK_BASE_EXT;
 
-		StationPickerDrawSprite(171, 35, RAILTYPE_BEGIN, image);
-		StationPickerDrawSprite(171, 85, RAILTYPE_BEGIN, image + 1);
+		StationPickerDrawSprite(171, 35, RAILTYPE_BEGIN, _cur_roadtype, image);
+		StationPickerDrawSprite(171, 85, RAILTYPE_BEGIN, _cur_roadtype, image + 1);
 
 		DrawStationCoverageAreaText(2, 146,
 			((w->window_class == WC_BUS_STATION) ? (1 << CT_PASSENGERS) : ~(1 << CT_PASSENGERS)),
--- a/src/road_map.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/road_map.cpp	Fri May 25 00:25:08 2007 +0000
@@ -14,13 +14,15 @@
 #include "depot.h"
 
 
-RoadBits GetAnyRoadBits(TileIndex tile)
+RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt)
 {
+	if (!HASBIT(GetRoadTypes(tile), rt)) return ROAD_NONE;
+
 	switch (GetTileType(tile)) {
 		case MP_STREET:
 			switch (GetRoadTileType(tile)) {
 				default:
-				case ROAD_TILE_NORMAL:   return GetRoadBits(tile);
+				case ROAD_TILE_NORMAL:   return GetRoadBits(tile, rt);
 				case ROAD_TILE_CROSSING: return GetCrossingRoadBits(tile);
 				case ROAD_TILE_DEPOT:    return DiagDirToRoadBits(GetRoadDepotDirection(tile));
 			}
@@ -44,15 +46,16 @@
 }
 
 
-TrackBits GetAnyRoadTrackBits(TileIndex tile)
+TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt)
 {
 	uint32 r;
 
 	/* Don't allow local authorities to build roads through road depots or road stops. */
-	if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || (IsTileType(tile, MP_STATION) && !IsDriveThroughStopTile(tile))) {
+	if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || (IsTileType(tile, MP_STATION) && !IsDriveThroughStopTile(tile)) || !HASBIT(GetRoadTypes(tile), rt)) {
 		return TRACK_BIT_NONE;
 	}
 
-	r = GetTileTrackStatus(tile, TRANSPORT_ROAD);
+	r = GetTileTrackStatus(tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(rt));
+
 	return (TrackBits)(byte)(r | (r >> 8));
 }
--- a/src/road_map.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/road_map.h	Fri May 25 00:25:08 2007 +0000
@@ -18,9 +18,9 @@
 };
 
 static inline RoadTileType GetRoadTileType(TileIndex t)
-{
+	{
 	assert(IsTileType(t, MP_STREET));
-	return (RoadTileType)GB(_m[t].m5, 4, 4);
+	return (RoadTileType)GB(_m[t].m5, 6, 2);
 }
 
 static inline bool IsLevelCrossing(TileIndex t)
@@ -33,23 +33,106 @@
 	return IsTileType(t, MP_STREET) && IsLevelCrossing(t);
 }
 
-static inline RoadBits GetRoadBits(TileIndex t)
+static inline RoadBits GetRoadBits(TileIndex t, RoadType rt)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_NORMAL);
-	return (RoadBits)GB(_m[t].m5, 0, 4);
+	switch (rt) {
+		default: NOT_REACHED();
+		case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4);
+		case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4);
+		case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4);
+	}
 }
 
-static inline void SetRoadBits(TileIndex t, RoadBits r)
+static inline RoadBits GetAllRoadBits(TileIndex tile)
+{
+	return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY);
+}
+
+static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); // XXX incomplete
-	SB(_m[t].m5, 0, 4, r);
+	switch (rt) {
+		default: NOT_REACHED();
+		case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break;
+		case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break;
+		case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break;
+	}
 }
 
+static inline RoadTypes GetRoadTypes(TileIndex t)
+{
+	if (IsTileType(t, MP_STREET)) {
+		return (RoadTypes)GB(_me[t].m7, 5, 3);
+	} else {
+		return (RoadTypes)GB(_m[t].m3, 0, 3);
+	}
+}
+
+static inline void SetRoadTypes(TileIndex t, RoadTypes rt)
+{
+	if (IsTileType(t, MP_STREET)) {
+		SB(_me[t].m7, 5, 3, rt);
+	} else {
+		assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
+		SB(_m[t].m3, 0, 2, rt);
+	}
+}
+
+static inline Owner GetRoadOwner(TileIndex t, RoadType rt)
+{
+	if (!IsTileType(t, MP_STREET)) return GetTileOwner(t);
+
+	switch (GetRoadTileType(t)) {
+		default: NOT_REACHED();
+		case ROAD_TILE_NORMAL:
+			switch (rt) {
+				default: NOT_REACHED();
+				case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5);
+				case ROADTYPE_TRAM: return (Owner)GB( _m[t].m5, 0, 5);
+				case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
+			}
+		case ROAD_TILE_CROSSING:
+			switch (rt) {
+				default: NOT_REACHED();
+				case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5);
+				case ROADTYPE_TRAM: return (Owner)GB( _m[t].m5, 0, 5);
+				case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
+			}
+		case ROAD_TILE_DEPOT: return GetTileOwner(t);
+	}
+}
+
+static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
+{
+	if (!IsTileType(t, MP_STREET)) return SetTileOwner(t, o);
+
+	switch (GetRoadTileType(t)) {
+		default: NOT_REACHED();
+		case ROAD_TILE_NORMAL:
+			switch (rt) {
+				default: NOT_REACHED();
+				case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break;
+				case ROADTYPE_TRAM: SB( _m[t].m5, 0, 5, o); break;
+				case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
+			}
+			break;
+		case ROAD_TILE_CROSSING:
+			switch (rt) {
+				default: NOT_REACHED();
+				case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break;
+				case ROADTYPE_TRAM: SB( _m[t].m5, 0, 5, o); break;
+				case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
+			}
+			break;
+		case ROAD_TILE_DEPOT: return SetTileOwner(t, o);
+	}
+}
 
 static inline Axis GetCrossingRoadAxis(TileIndex t)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	return (Axis)GB(_m[t].m5, 3, 1);
+	return (Axis)GB(_m[t].m4, 6, 1);
 }
 
 static inline RoadBits GetCrossingRoadBits(TileIndex tile)
@@ -63,35 +146,22 @@
 }
 
 
-// TODO swap owner of road and rail
-static inline Owner GetCrossingRoadOwner(TileIndex t)
-{
-	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	return (Owner)_m[t].m4;
-}
-
-static inline void SetCrossingRoadOwner(TileIndex t, Owner o)
-{
-	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	_m[t].m4 = o;
-}
-
 static inline void UnbarCrossing(TileIndex t)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	CLRBIT(_m[t].m5, 2);
+	CLRBIT(_m[t].m4, 5);
 }
 
 static inline void BarCrossing(TileIndex t)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	SETBIT(_m[t].m5, 2);
+	SETBIT(_m[t].m4, 5);
 }
 
 static inline bool IsCrossingBarred(TileIndex t)
 {
 	assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
-	return HASBIT(_m[t].m5, 2);
+	return HASBIT(_m[t].m4, 5);
 }
 
 #define IsOnDesert IsOnSnow
@@ -174,9 +244,10 @@
  * - bridge ramps: start of the ramp is treated as road piece
  * - bridge middle parts: bridge itself is ignored
  * @param tile the tile to get the road bits for
+ * @param rt   the road type to get the road bits form
  * @return the road bits of the given tile
  */
-RoadBits GetAnyRoadBits(TileIndex tile);
+RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt);
 
 /**
  * Get the accessible track bits for the given tile.
@@ -186,39 +257,45 @@
  * @param tile the tile to get the track bits for
  * @return the track bits for the given tile
  */
-TrackBits GetAnyRoadTrackBits(TileIndex tile);
+TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt);
 
 
-static inline void MakeRoadNormal(TileIndex t, Owner owner, RoadBits bits, TownID town)
+static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway)
 {
 	SetTileType(t, MP_STREET);
-	SetTileOwner(t, owner);
+	SetTileOwner(t, road);
 	_m[t].m2 = town;
-	_m[t].m3 = 0 << 7 | 0 << 4 | 0;
-	_m[t].m4 = 0;
-	_m[t].m5 = ROAD_TILE_NORMAL << 4 | bits;
+	_m[t].m3 = 0;
+	_m[t].m4 = (HASBIT(rot, ROADTYPE_TRAM) ? bits : 0) << 4 | (HASBIT(rot, ROADTYPE_ROAD) ? bits : 0);
+	_m[t].m5 = ROAD_TILE_NORMAL << 6 | tram;
+	SB(_m[t].m6, 2, 4, HASBIT(rot, ROADTYPE_HWAY) ? bits : 0);
+	_me[t].m7 = rot << 5 | hway;
 }
 
 
-static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner rail, Axis roaddir, RailType rt, uint town)
+static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner hway, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town)
 {
 	SetTileType(t, MP_STREET);
 	SetTileOwner(t, rail);
 	_m[t].m2 = town;
-	_m[t].m3 = 0 << 7 | 0 << 4 | rt;
-	_m[t].m4 = road;
-	_m[t].m5 = ROAD_TILE_CROSSING << 4 | roaddir << 3 | 0 << 2;
+	_m[t].m3 = rat;
+	_m[t].m4 = roaddir << 6 | road;
+	_m[t].m5 = ROAD_TILE_CROSSING << 6 | tram;
+	SB(_m[t].m6, 2, 4, 0);
+	_me[t].m7 = rot << 5 | hway;
 }
 
 
-static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir)
+static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, RoadType rt)
 {
 	SetTileType(t, MP_STREET);
 	SetTileOwner(t, owner);
 	_m[t].m2 = 0;
 	_m[t].m3 = 0;
 	_m[t].m4 = 0;
-	_m[t].m5 = ROAD_TILE_DEPOT << 4 | dir;
+	_m[t].m5 = ROAD_TILE_DEPOT << 6 | dir;
+	SB(_m[t].m6, 2, 4, 0);
+	_me[t].m7 = RoadTypeToRoadTypes(rt) << 5;
 }
 
 #endif /* ROAD_MAP_H */
--- a/src/roadveh_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/roadveh_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -173,6 +173,9 @@
 		v->u.road.state = RVSB_IN_DEPOT;
 		v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
 
+		v->u.road.roadtype = ROADTYPE_ROAD;
+		v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
+
 		v->spritenum = rvi->image_index;
 		v->cargo_type = rvi->cargo_type;
 		v->cargo_subtype = 0;
@@ -211,6 +214,8 @@
 		v->vehicle_flags = 0;
 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
+		v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity);
+
 		VehiclePositionChanged(v);
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -351,7 +356,7 @@
 		/* See where we are now */
 		Trackdir trackdir = GetVehicleTrackdir(v);
 
-		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE);
+		ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE);
 		if (ftd.best_bird_dist == 0) {
 			return GetDepotByTile(ftd.node.tile); /* Target found */
 		} else {
@@ -366,7 +371,7 @@
 
 		/* search in all directions */
 		for (DiagDirection i = DIAGDIR_BEGIN; i != DIAGDIR_END; i++) {
-			FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, i, EnumRoadSignalFindDepot, NULL, &rfdd);
+			FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, i, EnumRoadSignalFindDepot, NULL, &rfdd);
 		}
 
 		if (rfdd.best_length == (uint)-1) return NULL;
@@ -931,7 +936,7 @@
 {
 	uint32 bits;
 
-	bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD) & 0x3F;
+	bits = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->u.road.compatible_roadtypes) & 0x3F;
 
 	if (!(od->tilebits & bits) || (bits & 0x3C) || (bits & 0x3F3F0000))
 		return true;
@@ -957,7 +962,7 @@
 	/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
 	if (v->u.road.state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return;
 
-	tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F;
+	tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & 0x3F;
 	if ((tt & 3) == 0) return;
 	if ((tt & 0x3C) != 0) return;
 
@@ -1028,11 +1033,11 @@
 	return false;
 }
 
-static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
+static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
 {
 
 	void* perf = NpfBeginInterval();
-	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, owner, railtypes);
+	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, sub_type, owner, railtypes);
 	int t = NpfEndInterval(perf);
 	DEBUG(yapf, 4, "[NPFR] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
 	return ret;
@@ -1054,7 +1059,7 @@
 	FindRoadToChooseData frd;
 	Trackdir best_track;
 
-	uint32 r  = GetTileTrackStatus(tile, TRANSPORT_ROAD);
+	uint32 r  = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
 	TrackdirBits signal    = (TrackdirBits)GB(r, 16, 16);
 	TrackdirBits trackdirs = (TrackdirBits)GB(r,  0, 16);
 
@@ -1129,7 +1134,7 @@
 		trackdir = DiagdirToDiagTrackdir(enterdir);
 		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
 
-		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE);
+		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE);
 		if (ftd.best_trackdir == INVALID_TRACKDIR) {
 			/* We are already at our target. Just do something
 			 * @todo: maybe display error?
@@ -1179,7 +1184,7 @@
 				if (best_track == INVALID_TRACKDIR) best_track = (Trackdir)i; // in case we don't find the path, just pick a track
 				frd.maxtracklen = (uint)-1;
 				frd.mindist = (uint)-1;
-				FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
+				FollowTrack(tile, 0x2000 | TRANSPORT_ROAD, v->u.road.compatible_roadtypes, _road_pf_directions[i], EnumRoadTrackFindDist, NULL, &frd);
 
 				if (frd.mindist < best_dist || (frd.mindist == best_dist && frd.maxtracklen < best_maxlen)) {
 					best_dist = frd.mindist;
@@ -1212,7 +1217,7 @@
 		fstd.dest_coords = tile;
 		fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
 
-		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
+		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE).best_path_dist;
 		/* change units from NPF_TILE_LENGTH to # of tiles */
 		if (dist != UINT_MAX)
 			dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
@@ -1684,6 +1689,9 @@
 		return;
 	}
 
+	if (v->current_order.type == OT_LOADING) v->LeaveStation();
+	ClearSlot(v);
+
 	v->current_order.type = OT_GOTO_DEPOT;
 	v->current_order.flags = OF_NON_STOP;
 	v->current_order.dest = depot->index;
@@ -1849,7 +1857,7 @@
 		 * carry twice as much mail/goods as normal cargo, and four times as
 		 * many passengers
 		 */
-		capacity = rvi->capacity;
+		capacity = GetVehicleProperty(v, 0x0F, rvi->capacity);
 		switch (old_cid) {
 			case CT_PASSENGERS: break;
 			case CT_MAIL:
--- a/src/roadveh_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/roadveh_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -346,7 +346,7 @@
 
 	if (w != NULL) {
 		w->caption_color = v->owner;
-		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
+		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), ZOOM_LVL_ROADVEH);
 	}
 }
 
--- a/src/saveload.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/saveload.cpp	Fri May 25 00:25:08 2007 +0000
@@ -29,7 +29,7 @@
 #include <setjmp.h>
 #include <list>
 
-extern const uint16 SAVEGAME_VERSION = 59;
+extern const uint16 SAVEGAME_VERSION = 62;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
@@ -1257,6 +1257,7 @@
 extern const ChunkHandler _economy_chunk_handlers[];
 extern const ChunkHandler _animated_tile_chunk_handlers[];
 extern const ChunkHandler _newgrf_chunk_handlers[];
+extern const ChunkHandler _group_chunk_handlers[];
 
 static const ChunkHandler * const _chunk_handlers[] = {
 	_misc_chunk_handlers,
@@ -1274,6 +1275,7 @@
 	_player_chunk_handlers,
 	_animated_tile_chunk_handlers,
 	_newgrf_chunk_handlers,
+	_group_chunk_handlers,
 	NULL,
 };
 
--- a/src/screenshot.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/screenshot.cpp	Fri May 25 00:25:08 2007 +0000
@@ -449,7 +449,7 @@
 static void CurrentScreenCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n)
 {
 	for (; n > 0; --n) {
-		memcpy(buf, _screen.dst_ptr + y * _screen.pitch, _screen.width);
+		memcpy(buf, _screen.dst_ptr + y * _screen.pitch, _screen.width * sizeof(Pixel));
 		++y;
 		buf += pitch;
 	}
@@ -469,7 +469,7 @@
 	dpi.height = n;
 	dpi.width = vp->width;
 	dpi.pitch = pitch;
-	dpi.zoom = 0;
+	dpi.zoom = ZOOM_LVL_WORLD_SCREENSHOT;
 	dpi.left = 0;
 	dpi.top = y;
 
@@ -479,10 +479,10 @@
 		left += wx;
 
 		ViewportDoDraw(vp,
-			((left - wx - vp->left) << vp->zoom) + vp->virtual_left,
-			((y - vp->top) << vp->zoom) + vp->virtual_top,
-			((left - vp->left) << vp->zoom) + vp->virtual_left,
-			(((y + n) - vp->top) << vp->zoom) + vp->virtual_top
+			ScaleByZoom(left - wx - vp->left, vp->zoom) + vp->virtual_left,
+			ScaleByZoom(y - vp->top, vp->zoom) + vp->virtual_top,
+			ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left,
+			ScaleByZoom((y + n) - vp->top, vp->zoom) + vp->virtual_top
 		);
 	}
 
@@ -540,7 +540,7 @@
 	ViewPort vp;
 	const ScreenshotFormat *sf;
 
-	vp.zoom = 0;
+	vp.zoom = ZOOM_LVL_WORLD_SCREENSHOT;
 	vp.left = 0;
 	vp.top = 0;
 	vp.virtual_left = -(int)MapMaxX() * TILE_PIXELS;
--- a/src/settings.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/settings.cpp	Fri May 25 00:25:08 2007 +0000
@@ -1336,6 +1336,7 @@
 	SDT_VAR(Patches, scrollwheel_scrolling,SLE_UINT8,S,MS, 0,  0,  2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL),
 	SDT_VAR(Patches,scrollwheel_multiplier,SLE_UINT8,S, 0, 5,  1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,NULL),
 	SDT_BOOL(Patches, pause_on_newgame,              S, 0, false,        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,     NULL),
+	SDT_BOOL(Patches, advanced_vehicle_list,         S, 0, true,        STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,     NULL),
 
 	/***************************************************************************/
 	/* Construction section of the GUI-configure patches window */
@@ -1395,6 +1396,7 @@
 	SDT_BOOL(Patches, modified_catchment,      0, 0,  true,        STR_CONFIG_PATCHES_CATCHMENT,          NULL),
 	SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0,  true, STR_CONFIG_PATCHES_GRADUAL_LOADING,    NULL),
 	SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL),
+	SDT_CONDBOOL(Patches, adjacent_stations,      62, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL),
 
 	/***************************************************************************/
 	/* Economy section of the GUI-configure patches window */
--- a/src/settings_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/settings_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -598,6 +598,7 @@
 	"scrollwheel_scrolling",
 	"scrollwheel_multiplier",
 	"pause_on_newgame",
+	"advanced_vehicle_list",
 };
 
 static const char *_patches_construction[] = {
@@ -624,6 +625,7 @@
 	"modified_catchment",
 	"gradual_loading",
 	"road_stop_on_town_road",
+	"adjacent_stations",
 };
 
 static const char *_patches_economy[] = {
--- a/src/ship_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/ship_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -43,7 +43,7 @@
 
 static TrackBits GetTileShipTrackStatus(TileIndex tile)
 {
-	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
+	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER, 0);
 	return TrackdirBitsToTrackBits((TrackdirBits)(TRACKDIR_BIT_MASK & (r | r >> 8)));
 }
 
@@ -114,7 +114,7 @@
 	if (_patches.new_pathfinding_all) {
 		NPFFoundTargetData ftd;
 		Trackdir trackdir = GetVehicleTrackdir(v);
-		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
+		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPE);
 		if (ftd.best_bird_dist == 0) {
 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
 		} else {
@@ -165,6 +165,7 @@
 		return;
 	}
 
+	if (v->current_order.type == OT_LOADING) v->LeaveStation();
 	v->current_order.type = OT_GOTO_DEPOT;
 	v->current_order.flags = OF_NON_STOP;
 	v->current_order.dest = depot->index;
@@ -478,7 +479,7 @@
 		pfs.best_bird_dist = (uint)-1;
 		pfs.best_length = (uint)-1;
 
-		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
+		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
 
 		if (best_track != INVALID_TRACK) {
 			if (pfs.best_bird_dist != 0) {
@@ -513,7 +514,7 @@
 {
 
 	void* perf = NpfBeginInterval();
-	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, owner, railtypes);
+	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, 0, owner, railtypes);
 	int t = NpfEndInterval(perf);
 	DEBUG(yapf, 4, "[NPFW] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
 	return ret;
@@ -596,7 +597,7 @@
 
 static TrackBits GetAvailShipTracks(TileIndex tile, int dir)
 {
-	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
+	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER, 0);
 	return (TrackBits)((r | r >> 8) & _ship_sometracks[dir]);
 }
 
@@ -878,6 +879,8 @@
 		v->vehicle_flags = 0;
 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
+		v->cargo_cap = GetVehicleProperty(v, 0x0D, svi->capacity);
+
 		VehiclePositionChanged(v);
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -1090,7 +1093,7 @@
 	}
 
 	if (capacity == CALLBACK_FAILED) {
-		capacity = ShipVehInfo(v->engine_type)->capacity;
+		capacity = GetVehicleProperty(v, 0x0D, ShipVehInfo(v->engine_type)->capacity);
 	}
 	_returned_refit_capacity = capacity;
 
--- a/src/ship_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/ship_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -347,6 +347,6 @@
 
 	if (w != NULL) {
 		w->caption_color = v->owner;
-		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
+		AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), ZOOM_LVL_SHIP);
 	}
 }
--- a/src/signs.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/signs.cpp	Fri May 25 00:25:08 2007 +0000
@@ -68,8 +68,8 @@
 	MarkAllViewportsDirty(
 		si->sign.left - 6,
 		si->sign.top  - 3,
-		si->sign.left + si->sign.width_1 * 4 + 12,
-		si->sign.top  + 45);
+		si->sign.left + ScaleByZoom(si->sign.width_1 + 12, _cur_dpi->zoom),
+		si->sign.top  + ScaleByZoom(12, _cur_dpi->zoom));
 }
 
 /**
--- a/src/smallmap_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/smallmap_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -1016,8 +1016,8 @@
 				_scrolling_viewport = false;
 			}
 
-			WP(w, vp_d).scrollpos_x += e->we.scroll.delta.x << vp->zoom;
-			WP(w, vp_d).scrollpos_y += e->we.scroll.delta.y << vp->zoom;
+			WP(w, vp_d).scrollpos_x += ScaleByZoom(e->we.scroll.delta.x, vp->zoom);
+			WP(w, vp_d).scrollpos_y += ScaleByZoom(e->we.scroll.delta.y, vp->zoom);
 		} break;
 
 		case WE_MOUSEWHEEL:
@@ -1055,7 +1055,7 @@
 		/* the main window with the main view */
 		v = FindWindowById(WC_MAIN_WINDOW, 0);
 		/* New viewport start ats (zero,zero) */
-		AssignWindowViewport(w, 3, 17, 294, 214, 0 , 0);
+		AssignWindowViewport(w, 3, 17, 294, 214, 0 , ZOOM_LVL_VIEWPORT);
 
 		/* center on same place as main window (zoom is maximum, no adjustment needed) */
 		x = WP(v, vp_d).scrollpos_x;
--- a/src/sound.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/sound.cpp	Fri May 25 00:25:08 2007 +0000
@@ -152,7 +152,8 @@
 }
 
 
-static const byte _vol_factor_by_zoom[] = {255, 190, 134};
+static const byte _vol_factor_by_zoom[] = {255, 190, 134, 87, 49};
+assert_compile(lengthof(_vol_factor_by_zoom) == ZOOM_LVL_END);
 
 static const byte _sound_base_vol[] = {
 	128,  90, 128, 128, 128, 128, 128, 128,
--- a/src/station.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/station.cpp	Fri May 25 00:25:08 2007 +0000
@@ -125,8 +125,8 @@
 		MarkAllViewportsDirty(
 			sign.left - 6,
 			sign.top,
-			sign.left + (sign.width_1 << 2) + 12,
-			sign.top + 48);
+			sign.left + ScaleByZoom(sign.width_1 + 12, _cur_dpi->zoom),
+			sign.top + ScaleByZoom(12, _cur_dpi->zoom));
 	}
 }
 
--- a/src/station.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/station.h	Fri May 25 00:25:08 2007 +0000
@@ -10,6 +10,7 @@
 #include "oldpool.h"
 #include "sprite.h"
 #include "tile.h"
+#include "road.h"
 #include "newgrf_station.h"
 #include <list>
 
@@ -271,7 +272,7 @@
 
 
 const DrawTileSprites *GetStationTileLayout(byte gfx);
-void StationPickerDrawSprite(int x, int y, RailType railtype, int image);
+void StationPickerDrawSprite(int x, int y, RailType railtype, RoadType roadtype, int image);
 
 RoadStop * GetRoadStopByTile(TileIndex tile, RoadStop::Type type);
 uint GetNumRoadStops(const Station* st, RoadStop::Type type);
--- a/src/station_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/station_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -794,6 +794,7 @@
  * - p1 = (bit  0)    - orientation (Axis)
  * - p1 = (bit  8-15) - number of tracks
  * - p1 = (bit 16-23) - platform length
+ * - p1 = (bit 24)    - allow stations directly adjacent to other stations.
  * @param p2 various bitstuffed elements
  * - p2 = (bit  0- 3) - railtype (p2 & 0xF)
  * - p2 = (bit  8-15) - custom station class
@@ -838,9 +839,33 @@
 	if (CmdFailed(ret)) return ret;
 	int32 cost = ret + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len;
 
-	// Make sure there are no similar stations around us.
-	Station *st = GetStationAround(tile_org, w_org, h_org, est);
-	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	Station *st = NULL;
+	bool check_surrounding = true;
+
+	if (_patches.adjacent_stations) {
+		if (est != INVALID_STATION) {
+			if (HASBIT(p1, 24)) {
+				/* You can't build an adjacent station over the top of one that
+				 * already exists. */
+				return_cmd_error(STR_MUST_REMOVE_RAILWAY_STATION_FIRST);
+			} else {
+				/* Extend the current station, and don't check whether it will
+				 * be near any other stations. */
+				st = GetStation(est);
+				check_surrounding = false;
+			}
+		} else {
+			/* There's no station here. Don't check the tiles surrounding this
+			 * one if the player wanted to build an adjacent station. */
+			if (HASBIT(p1, 24)) check_surrounding = false;
+		}
+	}
+
+	if (check_surrounding) {
+		// Make sure there are no similar stations around us.
+		st = GetStationAround(tile_org, w_org, h_org, est);
+		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	}
 
 	// See if there is a deleted station close to us.
 	if (st == NULL) st = GetClosestStationFromTile(tile_org);
@@ -1214,6 +1239,8 @@
  * @param p1 entrance direction (DiagDirection)
  * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
  *           bit 1: 0 for normal, 1 for drive-through
+ *           bit 2..4: the roadtypes
+ *           bit 5: allow stations directly adjacent to other stations.
  */
 int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -1222,17 +1249,26 @@
 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
 	Owner cur_owner = _current_player;
+	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
+
+	if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
+
+	/* Trams only have drive through stops */
+	if (!is_drive_through && HASBIT(rts, ROADTYPE_TRAM)) return CMD_ERROR;
 
 	/* Saveguard the parameters */
 	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
 	/* If it is a drive-through stop check for valid axis */
 	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
 	/* Road bits in the wrong direction */
-	if (build_over_road && (GetRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
+	if (build_over_road && (GetAllRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
 	/* Not allowed to build over this road */
 	if (build_over_road) {
 		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
-		if (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetTileOwner(tile))) return CMD_ERROR;
+		if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) return CMD_ERROR;
+		if (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD)) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
+		/* Do not remove roadtypes! */
+		if (rts != GetRoadTypes(tile) && rts != ROADTYPES_ROADTRAM) return CMD_ERROR;
 	}
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1248,8 +1284,12 @@
 	if (CmdFailed(ret)) return ret;
 	int32 cost = build_over_road ? 0 : ret; // Don't add cost of clearing road when overbuilding
 
-	Station *st = GetStationAround(tile, 1, 1, INVALID_STATION);
-	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	Station *st = NULL;
+
+	if (!_patches.adjacent_stations || !HASBIT(p2, 5)) {
+		st = GetStationAround(tile, 1, 1, INVALID_STATION);
+		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	}
 
 	/* Find a station close to us */
 	if (st == NULL) st = GetClosestStationFromTile(tile);
@@ -1311,9 +1351,9 @@
 
 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
 		if (is_drive_through) {
-			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, (Axis)p1, town_owned_road);
+			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road);
 		} else {
-			MakeRoadStop(tile, st->owner, st->index, rs_type, (DiagDirection)p1);
+			MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
 		}
 
 		UpdateStationVirtCoordDirty(st);
@@ -1389,7 +1429,10 @@
 	Station *st = GetStationByTile(tile);
 	/* Save the stop info before it is removed */
 	bool is_drive_through = IsDriveThroughStopTile(tile);
-	RoadBits road_bits = GetAnyRoadBits(tile);
+	RoadTypes rts = GetRoadTypes(tile);
+	RoadBits road_bits = IsDriveThroughStopTile(tile) ?
+			((GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y) :
+			DiagDirToRoadBits(GetRoadStopDir(tile));
 	bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
 
 	int32 ret = RemoveRoadStop(st, flags, tile);
@@ -1403,7 +1446,12 @@
 			index = ClosestTownFromTile(tile, (uint)-1)->index;
 			_current_player = OWNER_TOWN;
 		}
-		DoCommand(tile, road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
+		if (HASBIT(rts, ROADTYPE_ROAD)) {
+			DoCommand(tile, ROADTYPE_ROAD << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
+		}
+		if (HASBIT(rts, ROADTYPE_TRAM)) {
+			DoCommand(tile, ROADTYPE_TRAM << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
+		}
 		_current_player = cur_owner;
 	}
 
@@ -1506,7 +1554,7 @@
  * @param tile tile where airport will be built
  * @param flags operation to perform
  * @param p1 airport type, @see airport.h
- * @param p2 unused
+ * @param p2 (bit 0) - allow airports directly adjacent to other airports.
  */
 int32 CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -1544,8 +1592,12 @@
 	if (CmdFailed(ret)) return ret;
 	int32 cost = ret;
 
-	Station *st = GetStationAround(tile, w, h, INVALID_STATION);
-	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	Station *st = NULL;
+
+	if (!_patches.adjacent_stations || !HASBIT(p2, 0)) {
+		st = GetStationAround(tile, w, h, INVALID_STATION);
+		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	}
 
 	/* Find a station close to us */
 	if (st == NULL) st = GetClosestStationFromTile(tile);
@@ -1790,7 +1842,7 @@
 /** Build a dock/haven.
  * @param tile tile where dock will be built
  * @param flags operation to perform
- * @param p1 unused
+ * @param p1 (bit 0) - allow docks directly adjacent to other docks.
  * @param p2 unused
  */
 int32 CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@@ -1832,10 +1884,14 @@
 	}
 
 	/* middle */
-	Station *st = GetStationAround(
-		tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
-		_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
-	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	Station *st = NULL;
+
+	if (!_patches.adjacent_stations || !HASBIT(p1, 0)) {
+		st = GetStationAround(
+				tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
+				_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
+		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
+	}
 
 	/* Find a station close to us */
 	if (st == NULL) st = GetClosestStationFromTile(tile);
@@ -2023,7 +2079,7 @@
 	}
 }
 
-void StationPickerDrawSprite(int x, int y, RailType railtype, int image)
+void StationPickerDrawSprite(int x, int y, RailType railtype, RoadType roadtype, int image)
 {
 	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
@@ -2076,7 +2132,7 @@
 }
 
 
-static uint32 GetTileTrackStatus_Station(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Station(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	switch (mode) {
 		case TRANSPORT_RAIL:
@@ -2098,7 +2154,7 @@
 			break;
 
 		case TRANSPORT_ROAD:
-			if (IsRoadStopTile(tile)) {
+			if ((GetRoadTypes(tile) & sub_mode) != 0 && IsRoadStopTile(tile)) {
 				return AxisToTrackBits(DiagDirToAxis(GetRoadStopDir(tile))) * 0x101;
 			}
 			break;
@@ -2676,7 +2732,8 @@
 	if (!GetStopBuiltOnTownRoad(tile)) return true;
 
 	bool edge_road;
-	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile), OWNER_TOWN, &edge_road);
+	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, &edge_road, ROADTYPE_ROAD) &&
+				CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM);
 }
 
 static int32 ClearTile_Station(TileIndex tile, byte flags)
--- a/src/station_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/station_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -686,7 +686,7 @@
 		sprite = cs->sprite;
 	}
 
-	if (sprite == 0) return;
+	if (sprite == 0) sprite = SPR_CARGO_GOODS;
 
 	do {
 		DrawSprite(sprite, PAL_NONE, x, y);
--- a/src/station_map.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/station_map.h	Fri May 25 00:25:08 2007 +0000
@@ -6,6 +6,7 @@
 #define STATION_MAP_H
 
 #include "rail_map.h"
+#include "road_map.h"
 #include "station.h"
 
 typedef byte StationGfx;
@@ -309,15 +310,17 @@
 	SetRailType(t, rt);
 }
 
-static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, DiagDirection d)
+static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, RoadTypes rt, DiagDirection d)
 {
 	MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE : GFX_TRUCK_BASE) + d);
+	SetRoadTypes(t, rt);
 }
 
-static inline void MakeDriveThroughRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, Axis a, bool on_town_road)
+static inline void MakeDriveThroughRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, RoadTypes rt, Axis a, bool on_town_road)
 {
 	MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE_EXT : GFX_TRUCK_BASE_EXT) + a);
 	SB(_m[t].m6, 3, 1, on_town_road);
+	SetRoadTypes(t, rt);
 }
 
 static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section)
--- a/src/stdafx.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/stdafx.h	Fri May 25 00:25:08 2007 +0000
@@ -112,7 +112,6 @@
 # define FORCEINLINE inline
 # define CDECL
 # define __int64 long long
-# define NOT_REACHED() assert(0)
 # define GCC_PACK __attribute__((packed))
 
 # if (__GNUC__ == 2)
@@ -125,7 +124,6 @@
 # define NORETURN
 # define FORCEINLINE inline
 # define CDECL
-# define NOT_REACHED() assert(0)
 # define GCC_PACK
 # include <malloc.h>
 #endif /* __WATCOMC__ */
@@ -164,11 +162,6 @@
 # define FORCEINLINE __forceinline
 # define inline _inline
 # define CDECL _cdecl
-# if defined(_DEBUG)
-#  define NOT_REACHED() assert(0)
-# else
-#  define NOT_REACHED() _assume(0)
-# endif /* _DEBUG */
   int CDECL snprintf(char *str, size_t size, const char *format, ...);
 # if _MSC_VER < 1400
    int CDECL vsnprintf(char *str, size_t size, const char *format, va_list ap);
@@ -336,4 +329,12 @@
 # define Point OTTD_AMIGA_POINT
 #endif
 
+void
+#ifndef STRGEN
+/* In strgen error is not fatal and returns */
+NORETURN
+#endif /* STRGEN */
+CDECL error(const char *str, ...);
+#define NOT_REACHED() error("NOT_REACHED triggered at line %i of %s", __LINE__, __FILE__)
+
 #endif /* STDAFX_H */
--- a/src/strgen/strgen.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/strgen/strgen.cpp	Fri May 25 00:25:08 2007 +0000
@@ -506,6 +506,7 @@
 	{"WAYPOINT", EmitSingleChar, SCC_WAYPOINT_NAME, 1, 0}, // waypoint name
 	{"STATION",  EmitSingleChar, SCC_STATION_NAME,  1, 0},
 	{"TOWN",     EmitSingleChar, SCC_TOWN_NAME,     1, 0},
+	{"GROUP",    EmitSingleChar, SCC_GROUP_NAME,    1, 0},
 
 	// 0x9D is used for the pseudo command SETCASE
 	// 0x9E is used for case switching
--- a/src/strings.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/strings.cpp	Fri May 25 00:25:08 2007 +0000
@@ -25,6 +25,8 @@
 #include "industry.h"
 #include "helpers.hpp"
 #include "cargotype.h"
+#include "group.h"
+#include "debug.h"
 
 /* for opendir/readdir/closedir */
 # include "fios.h"
@@ -840,6 +842,18 @@
 				break;
 			}
 
+			case SCC_GROUP_NAME: { // {GROUP}
+				const Group *g = GetGroup(GetInt32(&argv));
+				int32 args[1];
+
+				assert(IsValidGroup(g));
+
+				args[0] = g->index;
+				buff = GetStringWithArgs(buff, (g->string_id == STR_SV_GROUP_NAME) ? (StringID)STR_GROUP_NAME_FORMAT : g->string_id, args, last);
+
+				break;
+			}
+
 			case SCC_CURRENCY_64: { // {CURRENCY64}
 				buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), false, last);
 				break;
--- a/src/table/build_industry.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/build_industry.h	Fri May 25 00:25:08 2007 +0000
@@ -1079,9 +1079,23 @@
 #undef MK
 #undef MKEND
 
+/** Array with saw sound, for sawmill */
+static const uint8 _sawmill_sounds[] = { SND_28_SAWMILL };
+
+/** Array with whistle sound, for factory */
+static const uint8 _factory_sounds[] = { SND_03_FACTORY_WHISTLE };
+
+/** Array with 3 animal sounds, for farms */
+static const uint8 _farm_sounds[] = { SND_24_SHEEP, SND_25_COW, SND_26_HORSE };
+
+/** Array with... hem... a sound of toyland */
+static const uint8 _plastic_mine_sounds[] = { SND_33_PLASTIC_MINE };
+
 /**
  * Writes the properties of an industry into the IndustrySpec struct.
  * @param tbl  tile table
+ * @param sndc number of sounds
+ * @param snd  sounds table
  * @param d    cost multiplier
  * @param ai1  appear chance ingame - temperate
  * @param ai2  appear chance ingame - arctic
@@ -1102,8 +1116,11 @@
  * @param r2   rate of production 1
  * @param m    minimum cargo moved to station
  * @param a1   accepted cargo 1
+ * @param im1  input multiplier for cargo 1
  * @param a2   accepted cargo 2
+ * @param im2  input multiplier for cargo 2
  * @param a3   accepted cargo 3
+ * @param im3  input multiplier for cargo 3
  * @param pr   industry life (actually, the same as extractive, organic, processing in ttdpatch's specs)
  * @param clim climate availaility
  * @param bev  industry behaviour
@@ -1114,349 +1131,386 @@
  * @param s3   text for production down
  */
 
-#define MI(tbl, d, ai1, ai2, ai3, ai4, ag1, ag2, ag3, ag4, col, \
-           c1, c2, c3, proc, p1, r1, p2, r2, m, a1, a2, a3, pr, clim, bev, in, intx, s1, s2, s3) \
-	{tbl, lengthof(tbl), d, {c1, c2, c3}, proc, {p1, p2}, {r1, r2}, m,            \
-	 {a1, a2, a3}, pr, clim, bev, col, in, intx, s1, s2, s3, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, 0, 0, 0, 0}
-
+#define MI(tbl, sndc, snd, d, ai1, ai2, ai3, ai4, ag1, ag2, ag3, ag4, col, \
+           c1, c2, c3, proc, p1, r1, p2, r2, m, a1, im1, a2, im2, a3, im3, pr, clim, bev, in, intx, s1, s2, s3) \
+	 {tbl, lengthof(tbl), d, {c1, c2, c3}, proc, {p1, p2}, {r1, r2}, m,            \
+	 {a1, a2, a3}, {{im1, 0}, {im2, 0}, {im3, 0}}, pr, clim, bev, col, in, intx, s1, s2, s3, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, \
+	 sndc, snd, 0, {0, 0, NULL, NULL, INVALID_INDUSTRYTYPE, true}}
 static const IndustrySpec _industry_specs[] = {
 	/* Format:
-	   tile table                              cost multiplier   appear chances(4ingame, 4random)  map colour
+	   tile table                              count and sounds table
+	   cost multiplier                         appear chances(4ingame, 4random)  map colour
 	   cannot be close to these industries (3 times)             check proc
 	   (produced cargo + rate) (twice)         minimum cargo moved to station
-	   3 accepted cargo
+	   3 accepted cargo and their corresponding input multiplier
 	   industry life                           climate availability
 	   industry behaviours
 	   industry name                           building text
 	   messages : Closure                      production up                      production down   */
-	MI(_tile_table_coal_mine,                  210,              2, 3, 0, 0,    8, 8, 0, 0,        215,
+	MI(_tile_table_coal_mine,                  0, NULL,
+	   210,                                    2, 3, 0, 0,    8, 8, 0, 0,        215,
 	   IT_POWER_STATION,  IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_COAL,       15, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE | 1 << LT_ARCTIC,
 	   INDUSTRYBEH_CAN_SUBSIDENCE,
 	   STR_4802_COAL_MINE,                     STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4836_NEW_COAL_SEAM_FOUND_AT,   STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_power_station,              30,               2, 2, 0, 0,    5, 5, 0, 0,        184,
+	MI(_tile_table_power_station,              0, NULL,
+	   30,                                     2, 2, 0, 0,    5, 5, 0, 0,        184,
 	   IT_COAL_MINE,      IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_INVALID,     0, CT_INVALID,       0, 5,
-	   CT_COAL,           CT_INVALID,          CT_INVALID,
+	   CT_COAL,        0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_NOT_CLOSABLE,              1 << LT_TEMPERATE | 1 << LT_ARCTIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4803_POWER_STATION,                 STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_sawmill,                    28,               2, 0, 0, 0,    5, 0, 0, 0,        194,
+	MI(_tile_table_sawmill,                    1, _sawmill_sounds,
+	   28,                                     2, 0, 0, 0,    5, 0, 0, 0,        194,
 	   IT_FOREST,         IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_GOODS,       0, CT_INVALID,       0, 5,
-	   CT_WOOD,           CT_INVALID,          CT_INVALID,
+	   CT_WOOD,      256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TEMPERATE,
 	   INDUSTRYBEH_NONE,
 	   STR_4804_SAWMILL,                       STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_forest,                     200,              3, 4, 0, 0,    5, 5, 0, 0,         86,
+	MI(_tile_table_forest,                     0, NULL,
+	   200,                                    3, 4, 0, 0,    5, 5, 0, 0,         86,
 	   IT_SAWMILL,        IT_PAPER_MILL,       IT_INVALID,       CHECK_FOREST,
 	   CT_WOOD,       13, CT_INVALID,       0, 30,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE | 1 << LT_ARCTIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4805_FOREST,                        STR_482E_NEW_BEING_PLANTED_NEAR,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_oil_refinery,               31,               2, 2, 2, 0,    4, 4, 4, 0,        191,
+	MI(_tile_table_oil_refinery,               0, NULL,
+	   31,                                     2, 2, 2, 0,    4, 4, 4, 0,        191,
 	   IT_OIL_RIG,        IT_INVALID,          IT_INVALID,       CHECK_REFINERY,
 	   CT_GOODS,       0, CT_INVALID,       0, 5,
-	   CT_OIL,            CT_INVALID,          CT_INVALID,
+	   CT_OIL,       256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TEMPERATE | 1 << LT_ARCTIC | 1 << LT_TROPIC,
 	   INDUSTRYBEH_AIRPLANE_ATTACKS,
 	   STR_4806_OIL_REFINERY,                  STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_oil_rig,                    240,              6, 0, 0, 0,    0, 0, 0, 0,        152,
+	MI(_tile_table_oil_rig,                    0, NULL,
+	   240,                                    6, 0, 0, 0,    0, 0, 0, 0,        152,
 	   IT_OIL_REFINERY,   IT_INVALID,          IT_INVALID,       CHECK_OIL_RIG,
 	   CT_OIL,        15, CT_PASSENGERS,    2, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE,
 	   INDUSTRYBEH_BUILT_ONWATER | INDUSTRYBEH_AFTER_1960 | INDUSTRYBEH_AI_AIRSHIP_ROUTES,
 	   STR_4807_OIL_RIG,                       STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4837_NEW_OIL_RESERVES_FOUND,   STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_factory,                    26,               2, 0, 0, 0,    5, 0, 0, 0,        174,
+	MI(_tile_table_factory,                    1, _factory_sounds,
+	   26,                                     2, 0, 0, 0,    5, 0, 0, 0,        174,
 	   IT_FARM,           IT_STEEL_MILL,       IT_INVALID,       CHECK_NOTHING,
 	   CT_GOODS,       0, CT_INVALID,       0, 5,
-	   CT_LIVESTOCK,      CT_GRAIN,            CT_STEEL,
+	   CT_LIVESTOCK, 256, CT_GRAIN ,      256, CT_STEEL,    256,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TEMPERATE,
 	   INDUSTRYBEH_CHOPPER_ATTACKS,
 	   STR_4808_FACTORY,                       STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_printing_works,             26,               0, 2, 0, 0,    0, 5, 0, 0,        174,
+	MI(_tile_table_printing_works,             1, _factory_sounds,
+	   26,                                     0, 2, 0, 0,    0, 5, 0, 0,        174,
 	   IT_PAPER_MILL,     IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_GOODS,       0, CT_INVALID,       0, 5,
-	   CT_PAPER,          CT_INVALID,          CT_INVALID,
+	   CT_PAPER,     256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_ARCTIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4809_PRINTING_WORKS,                STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_steel_mill,                 27,               2, 0, 0, 0,    5, 0, 0, 0,         10,
+	MI(_tile_table_steel_mill,                 0, NULL,
+	   27,                                     2, 0, 0, 0,    5, 0, 0, 0,         10,
 	   IT_IRON_MINE,      IT_FACTORY,          IT_INVALID,       CHECK_NOTHING,
 	   CT_STEEL,       0, CT_INVALID,       0, 5,
-	   CT_IRON_ORE,       CT_INVALID,          CT_INVALID,
+	   CT_IRON_ORE,  256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TEMPERATE,
 	   INDUSTRYBEH_NONE,
 	   STR_480A_STEEL_MILL,                    STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_farm,                       250,              2, 4, 0, 0,    9, 9, 0, 0,         48,
+	MI(_tile_table_farm,                       3, _farm_sounds,
+	   250,                                    2, 4, 0, 0,    9, 9, 0, 0,         48,
 	   IT_FACTORY,        IT_FOOD_PROCESS,     IT_INVALID,       CHECK_FARM,
 	   CT_GRAIN,      10, CT_LIVESTOCK,    10, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE | 1 << LT_ARCTIC,
 	   INDUSTRYBEH_PLANT_FIELDS | INDUSTRYBEH_PLANT_ON_BUILT,
 	   STR_480B_FARM,                          STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_copper_mine,                205,              0, 0, 3, 0,    0, 0, 4, 0,         10,
+	MI(_tile_table_copper_mine,                0, NULL,
+	   205,                                    0, 0, 3, 0,    0, 0, 4, 0,         10,
 	   IT_FACTORY_2,      IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_COPPER_ORE, 10, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_480C_COPPER_ORE_MINE,               STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_oil_well,                   220,              0, 5, 3, 0,    4, 5, 5, 0,        152,
+	MI(_tile_table_oil_well,                   0, NULL,               220,              0, 5, 3, 0,    4, 5, 5, 0,        152,
 	   IT_OIL_REFINERY,   IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_OIL,        12, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE | 1 << LT_ARCTIC | 1 << LT_TROPIC,
 	   INDUSTRYBEH_DONT_INCR_PROD | INDUSTRYBEH_BEFORE_1950,
 	   STR_480D_OIL_WELLS,                     STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4837_NEW_OIL_RESERVES_FOUND,   STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_bank,                       193,              7, 0, 0, 0,    0, 0, 0, 0,         15,
+	MI(_tile_table_bank,                       0, NULL,
+	   193,                                    7, 0, 0, 0,    0, 0, 0, 0,         15,
 	   IT_BANK_TEMP,      IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_VALUABLES,   6, CT_INVALID,       0, 5,
-	   CT_VALUABLES,      CT_INVALID,          CT_INVALID,
+	   CT_VALUABLES,   0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_NOT_CLOSABLE,              1 << LT_TEMPERATE,
 	   INDUSTRYBEH_TOWN1200_MORE | INDUSTRYBEH_ONLY_INTOWN,
 	   STR_480E_BANK,                          STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_food_process,               26,               0, 2, 2, 0,    0, 3, 4, 0,         55,
+	MI(_tile_table_food_process,               0, NULL,
+	   26,                                     0, 2, 2, 0,    0, 3, 4, 0,         55,
 	   IT_FRUIT_PLANTATION, IT_FARM,           IT_FARM_2,        CHECK_NOTHING,
 	   CT_FOOD,        0, CT_INVALID,       0, 5,
-	   CT_FRUIT,          CT_MAIZE,            CT_INVALID,
+	   CT_FRUIT,     256, CT_MAIZE,       256, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_ARCTIC | 1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_480F_FOOD_PROCESSING_PLANT,         STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_paper_mill,                 28,               0, 2, 0, 0,    0, 5, 0, 0,         10,
+	MI(_tile_table_paper_mill,                 1, _sawmill_sounds,
+	   28,                                     0, 2, 0, 0,    0, 5, 0, 0,         10,
 	   IT_FOREST,         IT_PRINTING_WORKS,   IT_INVALID,       CHECK_NOTHING,
 	   CT_PAPER,       0, CT_INVALID,       0, 5,
-	   CT_WOOD,           CT_INVALID,          CT_INVALID,
+	   CT_WOOD,      256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_ARCTIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4810_PAPER_MILL,                    STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_gold_mine,                  208,              0, 3, 0, 0,    0, 4, 0, 0,        194,
+	MI(_tile_table_gold_mine,                  0, NULL,
+	   208,                                    0, 3, 0, 0,    0, 4, 0, 0,        194,
 	   IT_BANK_TROPIC_ARCTIC, IT_INVALID,      IT_INVALID,       CHECK_NOTHING,
 	   CT_GOLD,        7, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_ARCTIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4811_GOLD_MINE,                     STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_bank2,                      19,               0, 3, 3, 0,    0, 6, 5, 0,         15,
+	MI(_tile_table_bank2,                      0, NULL,
+	   19,                                     0, 3, 3, 0,    0, 6, 5, 0,         15,
 	   IT_GOLD_MINE,      IT_DIAMOND_MINE,     IT_INVALID,       CHECK_NOTHING,
 	   CT_INVALID,     0, CT_INVALID,       0, 5,
-	   CT_GOLD,           CT_INVALID,          CT_INVALID,
+	   CT_GOLD,      256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_NOT_CLOSABLE,              1 << LT_ARCTIC | 1 << LT_TROPIC,
 	   INDUSTRYBEH_ONLY_INTOWN,
 	   STR_4812_BANK,                          STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_diamond_mine,               213,              0, 0, 3, 0,    0, 0, 4, 0,        184,
+	MI(_tile_table_diamond_mine,               0, NULL,
+	   213,                                    0, 0, 3, 0,    0, 0, 4, 0,        184,
 	   IT_BANK_TROPIC_ARCTIC, IT_INVALID,      IT_INVALID,       CHECK_NOTHING,
 	   CT_DIAMONDS,    7, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4813_DIAMOND_MINE,                  STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_iron_mine,                  220,              2, 0, 0, 0,    5, 0, 0, 0,         55,
+	MI(_tile_table_iron_mine,                  0, NULL,
+	   220,                                    2, 0, 0, 0,    5, 0, 0, 0,         55,
 	   IT_STEEL_MILL,     IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_IRON_ORE,   10, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TEMPERATE,
 	   INDUSTRYBEH_NONE,
 	   STR_4814_IRON_ORE_MINE,                 STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_fruit_plantation,           225,              0, 0, 2, 0,    0, 0, 4, 0,         86,
+	MI(_tile_table_fruit_plantation,           0, NULL,
+	   225,                                    0, 0, 2, 0,    0, 0, 4, 0,         86,
 	   IT_FOOD_PROCESS,   IT_INVALID,          IT_INVALID,       CHECK_PLANTATION,
 	   CT_FRUIT,      10, CT_INVALID,       0, 15,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4815_FRUIT_PLANTATION,              STR_482E_NEW_BEING_PLANTED_NEAR,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_rubber_plantation,          218,              0, 0, 3, 0,    0, 0, 4, 0,         39,
+	MI(_tile_table_rubber_plantation,          0, NULL,
+	   218,                                    0, 0, 3, 0,    0, 0, 4, 0,         39,
 	   IT_FACTORY_2,      IT_INVALID,          IT_INVALID,       CHECK_PLANTATION,
 	   CT_RUBBER,     10, CT_INVALID,       0, 15,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4816_RUBBER_PLANTATION,             STR_482E_NEW_BEING_PLANTED_NEAR,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_water_supply,               199,              0, 0, 3, 0,    0, 0, 4, 0,         37,
+	MI(_tile_table_water_supply,               0, NULL,
+	   199,                                    0, 0, 3, 0,    0, 0, 4, 0,         37,
 	   IT_WATER_TOWER,    IT_INVALID,          IT_INVALID,       CHECK_WATER,
 	   CT_WATER,      12, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4817_WATER_SUPPLY,                  STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_water_tower,                14,               0, 0, 4, 0,    0, 0, 8, 0,        208,
+	MI(_tile_table_water_tower,                0, NULL,
+	   14,                                     0, 0, 4, 0,    0, 0, 8, 0,        208,
 	   IT_WATER_SUPPLY,   IT_INVALID,          IT_INVALID,       CHECK_WATER,
 	   CT_INVALID,     0, CT_INVALID,       0, 5,
-	   CT_WATER,          CT_INVALID,          CT_INVALID,
+	   CT_WATER,     256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_NOT_CLOSABLE,              1 << LT_TROPIC,
 	   INDUSTRYBEH_ONLY_INTOWN,
 	   STR_4818_WATER_TOWER,                   STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_factory2,                   26,               0, 0, 2, 0,    0, 0, 4, 0,        174,
+	MI(_tile_table_factory2,                   1, _factory_sounds,
+	   26,                                     0, 0, 2, 0,    0, 0, 4, 0,        174,
 	   IT_RUBBER_PLANTATION, IT_COPPER_MINE,   IT_LUMBER_MILL,   CHECK_PLANTATION,
 	   CT_GOODS,       0, CT_INVALID,       0, 5,
-	   CT_RUBBER,         CT_COPPER_ORE,       CT_WOOD,
+	   CT_RUBBER,    256, CT_COPPER_ORE,  256, CT_WOOD,      256,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TROPIC,
 	   INDUSTRYBEH_NONE,
 	   STR_4819_FACTORY,                       STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_farm2,                      250,              0, 0, 1, 0,    0, 0, 2, 0,         48,
+	MI(_tile_table_farm2,                      0, NULL,
+	   250,                                    0, 0, 1, 0,    0, 0, 2, 0,         48,
 	   IT_FOOD_PROCESS,   IT_INVALID,          IT_INVALID,       CHECK_PLANTATION,
 	   CT_MAIZE,      11, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TROPIC,
 	   INDUSTRYBEH_PLANT_FIELDS | INDUSTRYBEH_PLANT_ON_BUILT,
 	   STR_481A_FARM,                          STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_lumber_mill,                17,               0, 0, 0, 0,    0, 0, 0, 0,        194,
+	MI(_tile_table_lumber_mill,                0, NULL,
+	   17,                                     0, 0, 0, 0,    0, 0, 0, 0,        194,
 	   IT_FACTORY_2,      IT_INVALID,          IT_INVALID,       CHECK_LUMBERMILL,
 	   CT_WOOD,        0, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TROPIC,
 	   INDUSTRYBEH_CUT_TREES,
 	   STR_481B_LUMBER_MILL,                   STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4834_LACK_OF_NEARBY_TREES_CAUSES,   STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_cotton_candy,               195,              0, 0, 0, 3,    0, 0, 0, 5,         48,
+	MI(_tile_table_cotton_candy,               0, NULL,
+	   195,                                    0, 0, 0, 3,    0, 0, 0, 5,         48,
 	   IT_CANDY_FACTORY,  IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_COTTON_CANDY, 13, CT_INVALID,    0, 30,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_481C_COTTON_CANDY_FOREST,           STR_482E_NEW_BEING_PLANTED_NEAR,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_candy_factory,              26,               0, 0, 0, 3,    0, 0, 0, 5,        174,
+	MI(_tile_table_candy_factory,              0, NULL,
+	   26,                                     0, 0, 0, 3,    0, 0, 0, 5,        174,
 	   IT_COTTON_CANDY,   IT_TOFFEE_QUARRY,    IT_SUGAR_MINE,    CHECK_NOTHING,
 	   CT_CANDY,       0, CT_INVALID,       0, 5,
-	   CT_SUGAR,          CT_TOFFEE,           CT_COTTON_CANDY,
+	   CT_SUGAR,     256, CT_TOFFEE,      256, CT_COTTON_CANDY, 256,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_481D_CANDY_FACTORY,                 STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_battery_farm,               187,              0, 0, 0, 3,    0, 0, 0, 4,         39,
+	MI(_tile_table_battery_farm,               0, NULL,
+	   187,                                    0, 0, 0, 3,    0, 0, 0, 4,         39,
 	   IT_TOY_FACTORY,    IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_BATTERIES,  11, CT_INVALID,      0, 30,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_481E_BATTERY_FARM,                  STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4838_IMPROVED_FARMING_METHODS, STR_483A_INSECT_INFESTATION_CAUSES),
 
-	MI(_tile_table_cola_wells,                 193,              0, 0, 0, 3,    0, 0, 0, 5,         55,
+	MI(_tile_table_cola_wells,                 0, NULL,
+	   193,                                    0, 0, 0, 3,    0, 0, 0, 5,         55,
 	   IT_FIZZY_DRINK_FACTORY, IT_INVALID,     IT_INVALID,       CHECK_NOTHING,
 	   CT_COLA,       12, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_481F_COLA_WELLS,                    STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_toy_shop,                   17,               0, 0, 0, 3,    0, 0, 0, 4,        208,
+	MI(_tile_table_toy_shop,                   0, NULL,
+	   17,                                     0, 0, 0, 3,    0, 0, 0, 4,        208,
 	   IT_TOY_FACTORY,    IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_INVALID,     0, CT_INVALID,       0, 5,
-	   CT_TOYS,           CT_INVALID,          CT_INVALID,
+	   CT_TOYS,      256, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_NOT_CLOSABLE,              1 << LT_TOYLAND,
 	   INDUSTRYBEH_ONLY_NEARTOWN,
 	   STR_4820_TOY_SHOP,                      STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_toy_factory,                20,              0, 0, 0, 3,    0, 0, 0, 5,          10,
+	MI(_tile_table_toy_factory,                0, NULL,
+	   20,                                     0, 0, 0, 3,    0, 0, 0, 5,          10,
 	   IT_PLASTIC_FOUNTAINS, IT_BATTERY_FARM,  IT_TOY_SHOP,     CHECK_NOTHING,
 	   CT_TOYS,        0, CT_INVALID,       0, 5,
-	   CT_PLASTIC,        CT_BATTERIES,        CT_INVALID,
+	   CT_PLASTIC,   256, CT_BATTERIES,   256, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4821_TOY_FACTORY,                   STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_plastic_fountain,           192,              0, 0, 0, 3,    0, 0, 0, 5,         37,
+	MI(_tile_table_plastic_fountain,           1, _plastic_mine_sounds,
+	   192,                                    0, 0, 0, 3,    0, 0, 0, 5,         37,
 	   IT_TOY_FACTORY,    IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_PLASTIC,    14, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4822_PLASTIC_FOUNTAINS,             STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_fizzy_drink,                22,               0, 0, 0, 3,    0, 0, 0, 4,        184,
+	MI(_tile_table_fizzy_drink,                0, NULL,
+	   22,                                     0, 0, 0, 3,    0, 0, 0, 4,        184,
 	   IT_COLA_WELLS,     IT_BUBBLE_GENERATOR, IT_INVALID,       CHECK_NOTHING,
 	   CT_FIZZY_DRINKS, 0, CT_INVALID,      0, 5,
-	   CT_COLA,           CT_BUBBLES,          CT_INVALID,
+	   CT_COLA,       256, CT_BUBBLES,    256, CT_INVALID,     0,
 	   INDUSTRYLIFE_CLOSABLE,                  1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4823_FIZZY_DRINK_FACTORY,           STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4833_SUPPLY_PROBLEMS_CAUSE_TO,      STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_bubble_generator,           203,              0, 0, 0, 3,    0, 0, 0, 5,        152,
+	MI(_tile_table_bubble_generator,           0, NULL,
+	   203,                                    0, 0, 0, 3,    0, 0, 0, 5,        152,
 	   IT_FIZZY_DRINK_FACTORY, IT_INVALID,     IT_INVALID,       CHECK_BUBBLEGEN,
 	   CT_BUBBLES,    13, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4824_BUBBLE_GENERATOR,              STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_toffee_quarry,              213,              0, 0, 0, 3,    0, 0, 0, 5,        194,
+	MI(_tile_table_toffee_quarry,              0, NULL,
+	   213,                                    0, 0, 0, 3,    0, 0, 0, 5,        194,
 	   IT_CANDY_FACTORY,  IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_TOFFEE,     10, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4825_TOFFEE_QUARRY,                 STR_482D_NEW_UNDER_CONSTRUCTION,
 	   STR_4832_ANNOUNCES_IMMINENT_CLOSURE,    STR_4835_INCREASES_PRODUCTION,     STR_4839_PRODUCTION_DOWN_BY_50),
 
-	MI(_tile_table_sugar_mine,                 210,              0, 0, 0, 2,    0, 0, 0, 4,         15,
+	MI(_tile_table_sugar_mine,                 0, NULL,
+	   210,                                    0, 0, 0, 2,    0, 0, 0, 4,         15,
 	   IT_CANDY_FACTORY,  IT_INVALID,          IT_INVALID,       CHECK_NOTHING,
 	   CT_SUGAR,      11, CT_INVALID,       0, 5,
-	   CT_INVALID,        CT_INVALID,          CT_INVALID,
+	   CT_INVALID,     0, CT_INVALID,       0, CT_INVALID,     0,
 	   INDUSTRYLIFE_PRODUCTION,                1 << LT_TOYLAND,
 	   INDUSTRYBEH_NONE,
 	   STR_4826_SUGAR_MINE,                    STR_482D_NEW_UNDER_CONSTRUCTION,
@@ -1473,7 +1527,7 @@
  * @param a2 next frame of animation
  * @param a3 chooses between animation or construction state
  */
-#define MT(c1, c2, c3, sl, a1, a2, a3) {{c1, c2, c3}, sl, a1, a2, a3}
+#define MT(c1, c2, c3, sl, a1, a2, a3) {{c1, c2, c3}, sl, a1, a2, a3, 0, {0, 0, NULL, NULL, 0, true}}
 static const IndustryTileSpec _industry_tile_specs[] = {
 	/* Coal Mine */
 	MT(CT_INVALID,      CT_INVALID,   CT_INVALID,    SLOPE_STEEP,  INDUTILE_NOANIM,   INDUTILE_NOANIM,  false),
--- a/src/table/cargo_const.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/cargo_const.h	Fri May 25 00:25:08 2007 +0000
@@ -17,10 +17,16 @@
 		STR_0011_MAIL,           STR_0031_MAIL,           STR_BAGS,       STR_QUANTITY_MAIL,         STR_ABBREV_MAIL,
 		SPR_CARGO_MAIL,          CC_MAIL        ),
 
+	/* Oil in temperate and arctic */
 	MK(  3, 'OIL_', 174, 16, 4437, 25, 255, true,  TE_NONE,
 		STR_0012_OIL,            STR_0032_OIL,            STR_LITERS,     STR_QUANTITY_OIL,          STR_ABBREV_OIL,
 		SPR_CARGO_OIL,           CC_LIQUID      ),
 
+	/* Oil in subtropic */
+	MK(  3, 'OIL_', 174, 16, 4892, 25, 255, true,  TE_NONE,
+		STR_0012_OIL,            STR_0032_OIL,            STR_LITERS,     STR_QUANTITY_OIL,          STR_ABBREV_OIL,
+		SPR_CARGO_OIL,           CC_LIQUID      ),
+
 	MK(  4, 'LVST', 208,  3, 4322,  4,  18, true,  TE_NONE,
 		STR_0013_LIVESTOCK,      STR_0033_LIVESTOCK,      STR_ITEMS,      STR_QUANTITY_LIVESTOCK,    STR_ABBREV_LIVESTOCK,
 		SPR_CARGO_LIVESTOCK,     CC_PIECE_GOODS ),
@@ -37,14 +43,20 @@
 		STR_0022_WHEAT,          STR_0042_WHEAT,          STR_TONS,       STR_QUANTITY_WHEAT,        STR_ABBREV_WHEAT,
 		SPR_CARGO_GRAIN,         CC_BULK        ),
 
-	MK(  6, 'MAIZ', 191,  6, 4778,  4,  40, true,  TE_NONE,
+	MK(  6, 'MAIZ', 191,  6, 4322,  4,  40, true,  TE_NONE,
 		STR_001B_MAIZE,          STR_003B_MAIZE,          STR_TONS,       STR_QUANTITY_MAIZE,        STR_ABBREV_MAIZE,
 		SPR_CARGO_GRAIN,         CC_BULK        ),
 
+	/* Wood in temperate and arctic */
 	MK(  7, 'WOOD',  84, 16, 5005, 15, 255, true,  TE_NONE,
 		STR_0016_WOOD,           STR_0036_WOOD,           STR_TONS,       STR_QUANTITY_WOOD,         STR_ABBREV_WOOD,
 		SPR_CARGO_WOOD,          CC_PIECE_GOODS ),
 
+	/* Wood in subtropic */
+	MK(  7, 'WOOD',  84, 16, 7964, 15, 255, true,  TE_NONE,
+		STR_0016_WOOD,           STR_0036_WOOD,           STR_TONS,       STR_QUANTITY_WOOD,         STR_ABBREV_WOOD,
+		SPR_CARGO_WOOD,          CC_PIECE_GOODS ),
+
 	MK(  8, 'IORE', 184, 16, 5120,  9, 255, true,  TE_NONE,
 		STR_0017_IRON_ORE,       STR_0037_IRON_ORE,       STR_TONS,       STR_QUANTITY_IRON_ORE,     STR_ABBREV_IRON_ORE,
 		SPR_CARGO_IRON_ORE,      CC_BULK        ),
@@ -57,15 +69,15 @@
 		STR_0019_VALUABLES,      STR_0039_VALUABLES,      STR_BAGS,       STR_QUANTITY_VALUABLES,    STR_ABBREV_VALUABLES,
 		SPR_CARGO_VALUES_GOLD,   CC_ARMOURED    ),
 
-	MK( 10, 'GOLD', 202,  8, 7509, 10,  40, true,  TE_NONE,
+	MK( 10, 'GOLD', 202,  8, 5802, 10,  40, true,  TE_NONE,
 		STR_0020_GOLD,           STR_0040_GOLD,           STR_BAGS,       STR_QUANTITY_GOLD,         STR_ABBREV_GOLD,
 		SPR_CARGO_VALUES_GOLD,   CC_ARMOURED    ),
 
-	MK( 10, 'DIAM', 202,  2, 7509, 10, 255, true,  TE_NONE,
+	MK( 10, 'DIAM', 202,  2, 5802, 10, 255, true,  TE_NONE,
 		STR_001D_DIAMONDS,       STR_003D_DIAMOND,        STR_BAGS,       STR_QUANTITY_DIAMONDS,     STR_ABBREV_DIAMONDS,
 		SPR_CARGO_DIAMONDS,      CC_ARMOURED    ),
 
-	MK( 11, 'PAPR',  10, 16, 5688,  7,  60, true,  TE_NONE,
+	MK( 11, 'PAPR',  10, 16, 5461,  7,  60, true,  TE_NONE,
 		STR_001F_PAPER,          STR_003F_PAPER,          STR_TONS,       STR_QUANTITY_PAPER,        STR_ABBREV_PAPER,
 		SPR_CARGO_PAPER,         CC_PIECE_GOODS ),
 
@@ -73,27 +85,27 @@
 		STR_001E_FOOD,           STR_003E_FOOD,           STR_TONS,       STR_QUANTITY_FOOD,         STR_ABBREV_FOOD,
 		SPR_CARGO_FOOD,          CC_EXPRESS     | CC_REFRIGERATED),
 
-	MK( 13, 'FRUT', 208,  6, 4322,  0,  15, true,  TE_NONE,
+	MK( 13, 'FRUT', 208,  6, 4209,  0,  15, true,  TE_NONE,
 		STR_001C_FRUIT,          STR_003C_FRUIT,          STR_TONS,       STR_QUANTITY_FRUIT,        STR_ABBREV_FRUIT,
 		SPR_CARGO_FRUIT,         CC_BULK        | CC_REFRIGERATED),
 
-	MK( 14, 'CORE', 184,  6, 5120, 12, 255, true,  TE_NONE,
+	MK( 14, 'CORE', 184,  6, 4892, 12, 255, true,  TE_NONE,
 		STR_001A_COPPER_ORE,     STR_003A_COPPER_ORE,     STR_TONS,       STR_QUANTITY_COPPER_ORE,   STR_ABBREV_COPPER_ORE,
 		SPR_CARGO_COPPER_ORE,    CC_BULK        ),
 
-	MK( 15, 'WATR',  10,  6, 5688, 20,  80, true,  TE_WATER,
+	MK( 15, 'WATR',  10,  6, 4664, 20,  80, true,  TE_WATER,
 		STR_0021_WATER,          STR_0041_WATER,          STR_LITERS,     STR_QUANTITY_WATER,        STR_ABBREV_WATER,
 		SPR_CARGO_WATERCOLA,     CC_LIQUID      ),
 
-	MK( 16, 'RUBR',  32,  6, 5916,  2,  20, true,  TE_NONE,
+	MK( 16, 'RUBR',  32,  6, 4437,  2,  20, true,  TE_NONE,
 		STR_0023_RUBBER,         STR_0043_RUBBER,         STR_LITERS,     STR_QUANTITY_RUBBER,       STR_ABBREV_RUBBER,
 		SPR_CARGO_RUBBER,        CC_LIQUID      ),
 
-	MK( 17, 'SUGR',  32, 16, 5916, 20, 255, true,  TE_NONE,
+	MK( 17, 'SUGR',  32, 16, 4437, 20, 255, true,  TE_NONE,
 		STR_0024_SUGAR,          STR_0044_SUGAR,          STR_TONS,       STR_QUANTITY_SUGAR,        STR_ABBREV_SUGAR,
 		SPR_CARGO_SUGAR,         CC_BULK        ),
 
-	MK( 18, 'TOYS', 174,  2, 4437, 25, 255, true,  TE_NONE,
+	MK( 18, 'TOYS', 174,  2, 5574, 25, 255, true,  TE_NONE,
 		STR_0025_TOYS,           STR_0045_TOY,            STR_NOTHING,    STR_QUANTITY_TOYS,         STR_ABBREV_TOYS,
 		SPR_CARGO_TOYS,          CC_PIECE_GOODS ),
 
@@ -109,23 +121,23 @@
 		STR_002A_TOFFEE,         STR_004A_TOFFEE,         STR_TONS,       STR_QUANTITY_TOFFEE,       STR_ABBREV_TOFFEE,
 		SPR_CARGO_TOFFEE,        CC_BULK        ),
 
-	MK( 22, 'COLA',  84, 16, 5005,  5,  75, true,  TE_NONE,
+	MK( 22, 'COLA',  84, 16, 4892,  5,  75, true,  TE_NONE,
 		STR_0027_COLA,           STR_0047_COLA,           STR_LITERS,     STR_QUANTITY_COLA,         STR_ABBREV_COLA,
 		SPR_CARGO_WATERCOLA,     CC_LIQUID      ),
 
-	MK( 23, 'CTCD', 184, 16, 5120, 10,  25, true,  TE_NONE,
+	MK( 23, 'CTCD', 184, 16, 5005, 10,  25, true,  TE_NONE,
 		STR_0028_COTTON_CANDY,   STR_0048_COTTON_CANDY,   STR_TONS,       STR_QUANTITY_CANDYFLOSS,   STR_ABBREV_CANDYFLOSS,
 		SPR_CARGO_COTTONCANDY,   CC_BULK        ),
 
-	MK( 24, 'BUBL',  10,  1, 5688, 20,  80, true,  TE_NONE,
+	MK( 24, 'BUBL',  10,  1, 5077, 20,  80, true,  TE_NONE,
 		STR_0029_BUBBLES,        STR_0049_BUBBLE,         STR_NOTHING,    STR_QUANTITY_BUBBLES,      STR_ABBREV_BUBBLES,
 		SPR_CARGO_BUBBLES,       CC_PIECE_GOODS ),
 
-	MK( 25, 'PLST', 202, 16, 7509, 30, 255, true,  TE_NONE,
+	MK( 25, 'PLST', 202, 16, 4664, 30, 255, true,  TE_NONE,
 		STR_002C_PLASTIC,        STR_004C_PLASTIC,        STR_LITERS,     STR_QUANTITY_PLASTIC,      STR_ABBREV_PLASTIC,
 		SPR_CARGO_PLASTIC,       CC_LIQUID      ),
 
-	MK( 26, 'FZDR',  48,  2, 5688, 30,  50, true,  TE_FOOD,
+	MK( 26, 'FZDR',  48,  2, 6250, 30,  50, true,  TE_FOOD,
 		STR_002D_FIZZY_DRINKS,   STR_004D_FIZZY_DRINK,    STR_NOTHING,    STR_QUANTITY_FIZZY_DRINKS, STR_ABBREV_FIZZY_DRINKS,
 		SPR_CARGO_FIZZYDRINK,    CC_PIECE_GOODS ),
 
@@ -136,7 +148,7 @@
 static const CargoLabel _default_climate_cargo[NUM_LANDSCAPE][12] = {
 	{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'GRAI', 'WOOD', 'IORE', 'STEL', 'VALU', 'VOID', },
 	{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'WHEA', 'WOOD', 'VOID', 'PAPR', 'GOLD', 'FOOD', },
-	{ 'PASS', 'RUBR', 'MAIL', 'OIL_', 'FRUT', 'GOOD', 'MAIZ', 'WOOD', 'CORE', 'WATR', 'DIAM', 'FOOD', },
+	{ 'PASS', 'RUBR', 'MAIL',      4, 'FRUT', 'GOOD', 'MAIZ',     11, 'CORE', 'WATR', 'DIAM', 'FOOD', },
 	{ 'PASS', 'SUGR', 'MAIL', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR', },
 };
 
--- a/src/table/control_codes.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/control_codes.h	Fri May 25 00:25:08 2007 +0000
@@ -26,6 +26,7 @@
 	SCC_WAYPOINT_NAME,
 	SCC_STATION_NAME,
 	SCC_TOWN_NAME,
+	SCC_GROUP_NAME,
 
 	SCC_CURRENCY_COMPACT,
 	SCC_CURRENCY_COMPACT_64,
--- a/src/table/engines.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/engines.h	Fri May 25 00:25:08 2007 +0000
@@ -19,7 +19,7 @@
  * @note the 0x80 in parameter b sets the "is carriage bit"
  * @note the 5 between d and e is the load amount
  */
-#define MK(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, e, 0, 8, 0, 0 }
+#define MK(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, e, 0, 8, 0, 0, 0 }
 
 /** Writes the properties of a train carriage into the EngineInfo struct.
  * @param a Introduction date
@@ -30,7 +30,7 @@
  * @see MK
  * @note the 5 between d and e is the load amount
  */
-#define MW(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b | 0x80, 5, e, 0, 8, 0, 0 }
+#define MW(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b | 0x80, 5, e, 0, 8, 0, 0, 0 }
 
 /** Writes the properties of a ship into the EngineInfo struct.
  * @param a Introduction date
@@ -41,7 +41,7 @@
  * @see MK
  * @note the 10 between d and e is the load amount
  */
-#define MS(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, e, 0, 8, 0, 0 }
+#define MS(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, e, 0, 8, 0, 0, 0 }
 
 /** Writes the properties of an aeroplane into the EngineInfo struct.
  * @param a Introduction date
@@ -52,7 +52,7 @@
  * @see MK
  * @note the 20 between d and e is the load amount
  */
-#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, 0, 8, 0, 0 }
+#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, 0, 8, 0, 0, 0 }
 
 // Climates
 // T = Temperate
--- a/src/table/files.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/files.h	Fri May 25 00:25:08 2007 +0000
@@ -62,4 +62,5 @@
 	{ "openttd.grf",   { 0x85, 0x4f, 0xf6, 0xb5, 0xd2, 0xf7, 0xbc, 0x1e, 0xb9, 0xdc, 0x44, 0xef, 0x35, 0x5f, 0x64, 0x9b } },
 	{ "trkfoundw.grf", { 0x12, 0x33, 0x3f, 0xa3, 0xd1, 0x86, 0x8b, 0x04, 0x53, 0x18, 0x9c, 0xee, 0xf9, 0x2d, 0xf5, 0x95 } },
 	{ "roadstops.grf", { 0x8c, 0xd9, 0x45, 0x21, 0x28, 0x82, 0x96, 0x45, 0x33, 0x22, 0x7a, 0xb9, 0x0d, 0xf3, 0x67, 0x4a } },
+	{ "group.grf",     { 0xe8, 0x52, 0x5f, 0x1c, 0x3e, 0xf9, 0x91, 0x9d, 0x0f, 0x70, 0x8c, 0x8a, 0x21, 0xa4, 0xc7, 0x02 } },
 };
--- a/src/table/sprites.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/sprites.h	Fri May 25 00:25:08 2007 +0000
@@ -128,6 +128,28 @@
 	SPR_TRUCK_STOP_DT_X_W = SPR_ROADSTOP_BASE + 6,
 	SPR_TRUCK_STOP_DT_X_E = SPR_ROADSTOP_BASE + 7,
 
+	SPR_GROUP_BASE                 = SPR_ROADSTOP_BASE + 8, // The sprites used for the group interface
+	SPR_GROUP_CREATE_TRAIN         = SPR_GROUP_BASE,
+	SPR_GROUP_CREATE_ROADVEH       = SPR_GROUP_BASE + 1,
+	SPR_GROUP_CREATE_SHIP          = SPR_GROUP_BASE + 2,
+	SPR_GROUP_CREATE_AIRCRAFT      = SPR_GROUP_BASE + 3,
+	SPR_GROUP_DELETE_TRAIN         = SPR_GROUP_BASE + 4,
+	SPR_GROUP_DELETE_ROADVEH       = SPR_GROUP_BASE + 5,
+	SPR_GROUP_DELETE_SHIP          = SPR_GROUP_BASE + 6,
+	SPR_GROUP_DELETE_AIRCRAFT      = SPR_GROUP_BASE + 7,
+	SPR_GROUP_RENAME_TRAIN         = SPR_GROUP_BASE + 8,
+	SPR_GROUP_RENAME_ROADVEH       = SPR_GROUP_BASE + 9,
+	SPR_GROUP_RENAME_SHIP          = SPR_GROUP_BASE + 10,
+	SPR_GROUP_RENAME_AIRCRAFT      = SPR_GROUP_BASE + 11,
+	SPR_GROUP_REPLACE_ON_TRAIN     = SPR_GROUP_BASE + 12,
+	SPR_GROUP_REPLACE_ON_ROADVEH   = SPR_GROUP_BASE + 13,
+	SPR_GROUP_REPLACE_ON_SHIP      = SPR_GROUP_BASE + 14,
+	SPR_GROUP_REPLACE_ON_AIRCRAFT  = SPR_GROUP_BASE + 15,
+	SPR_GROUP_REPLACE_OFF_TRAIN    = SPR_GROUP_BASE + 16,
+	SPR_GROUP_REPLACE_OFF_ROADVEH  = SPR_GROUP_BASE + 17,
+	SPR_GROUP_REPLACE_OFF_SHIP     = SPR_GROUP_BASE + 18,
+	SPR_GROUP_REPLACE_OFF_AIRCRAFT = SPR_GROUP_BASE + 19,
+
 	/* Manager face sprites */
 	SPR_GRADIENT = 874, // background gradient behind manager face
 
--- a/src/table/town_land.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/table/town_land.h	Fri May 25 00:25:08 2007 +0000
@@ -1804,7 +1804,7 @@
  */
 #define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \
 	{mnd, mxd, p, rc, bn, rr, mg, {ca1, ca2, ca3}, {cg1, cg2, cg3}, bf, ba, true, \
-	 0, NULL, 0, 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, 0, 2, 0, 0, NULL}
+	 0, NULL, 0, 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, 0, 2, 0, 0, 0, NULL}
 /** House specifications from original data */
 static const HouseSpec _original_house_specs[] = {
 	/**
--- a/src/terraform_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/terraform_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -104,23 +104,24 @@
 	TileIndex start_tile = e->we.place.starttile;
 	TileIndex end_tile = e->we.place.tile;
 
-	switch (e->we.place.userdata >> 4) {
-	case GUI_PlaceProc_DemolishArea >> 4:
-		DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
-		break;
-	case GUI_PlaceProc_LevelArea >> 4:
-		DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO);
-		break;
-	case GUI_PlaceProc_RockyArea >> 4:
-		GenerateRockyArea(end_tile, start_tile);
-		break;
-	case GUI_PlaceProc_DesertArea >> 4:
-		GenerateDesertArea(end_tile, start_tile);
-		break;
-	case GUI_PlaceProc_WaterArea >> 4:
-		DoCommandP(end_tile, start_tile, _ctrl_pressed, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
-		break;
-	default: return false;
+	switch (e->we.place.select_proc) {
+		case DDSP_DEMOLISH_AREA:
+			DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
+			break;
+		case DDSP_LEVEL_AREA:
+			DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_LEVEL_LAND | CMD_AUTO);
+			break;
+		case DDSP_CREATE_ROCKS:
+			GenerateRockyArea(end_tile, start_tile);
+			break;
+		case DDSP_CREATE_DESERT:
+			GenerateDesertArea(end_tile, start_tile);
+			break;
+		case DDSP_CREATE_WATER:
+			DoCommandP(end_tile, start_tile, _ctrl_pressed, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
+			break;
+		default:
+			return false;
 	}
 
 	return true;
@@ -140,7 +141,7 @@
 
 void PlaceProc_DemolishArea(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_DEMOLISH_AREA);
 }
 
 static void PlaceProc_RaiseLand(TileIndex tile)
@@ -161,7 +162,7 @@
 
 void PlaceProc_LevelLand(TileIndex tile)
 {
-	VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_LevelArea);
+	VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA);
 }
 
 static void TerraformClick_Lower(Window *w)
@@ -239,13 +240,17 @@
 		return;
 
 	case WE_PLACE_DRAG:
-		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata & 0xF);
+		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
 		break;
 
 	case WE_PLACE_MOUSEUP:
-		if (e->we.place.pt.x != -1 &&
-				(e->we.place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
-			GUIPlaceProcDragXY(e);
+		if (e->we.place.pt.x != -1) {
+			switch (e->we.place.select_proc) {
+				case DDSP_DEMOLISH_AREA:
+				case DDSP_LEVEL_AREA:
+					GUIPlaceProcDragXY(e);
+					break;
+			}
 		}
 		break;
 
--- a/src/texteff.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/texteff.cpp	Fri May 25 00:25:08 2007 +0000
@@ -327,7 +327,7 @@
 	const TextEffect* te;
 
 	switch (dpi->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			for (te = _text_effect_list; te != endof(_text_effect_list); te++) {
 				if (te->string_id != INVALID_STRING_ID &&
 						dpi->left <= te->right &&
@@ -339,7 +339,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			for (te = _text_effect_list; te != endof(_text_effect_list); te++) {
 				if (te->string_id != INVALID_STRING_ID &&
 						dpi->left <= te->right  * 2 - te->x &&
@@ -350,6 +350,13 @@
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 }
 
--- a/src/town.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/town.h	Fri May 25 00:25:08 2007 +0000
@@ -164,10 +164,10 @@
 	CargoID accepts_cargo[3];          ///< 3 input cargo slots
 	BuildingFlags building_flags;      ///< some flags that describe the house (size, stadium etc...)
 	HouseZones building_availability;  ///< where can it be built (climates, zones)
-	bool enabled;                      ///< the house is still avaible (by default, true.newgrf can disable it, though)
+	bool enabled;                      ///< the house is available to build (true by default, but can be disabled by newgrf)
 
 	/* NewHouses properties */
-	HouseID substitute_id;             ///< which house this one is based on
+	HouseID substitute_id;             ///< which original house this one is based on
 	struct SpriteGroup *spritegroup;   ///< pointer to the different sprites of the house
 	HouseID override;                  ///< which house this one replaces
 	uint16 callback_mask;              ///< House callback flags
@@ -178,6 +178,7 @@
 	byte animation_frames;             ///< number of animation frames
 	byte animation_speed;              ///< amount of time between each of those frames
 	byte processing_time;              ///< Periodic refresh multiplier
+	byte minimum_life;                 ///< The minimum number of years this house will survive before the town rebuilds it
 
 	/* grf file related properties*/
 	uint8 local_id;                    ///< id defined by the grf file for this house
--- a/src/town_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/town_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -38,6 +38,7 @@
 #include "newgrf.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_house.h"
+#include "newgrf_commons.h"
 
 /**
  * Called if a new block is added to the town-pool
@@ -343,7 +344,7 @@
 
 	/* Check and/or  */
 	if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) {
-		uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
 	}
 
@@ -399,24 +400,55 @@
 
 	r = Random();
 
-	if (GB(r, 0, 8) < hs->population) {
-		uint amt = GB(r, 0, 8) / 8 + 1;
-		uint moved;
-
-		if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
-		t->new_max_pass += amt;
-		moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
-		t->new_act_pass += moved;
-	}
-
-	if (GB(r, 8, 8) < hs->mail_generation) {
-		uint amt = GB(r, 8, 8) / 8 + 1;
-		uint moved;
-
-		if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
-		t->new_max_mail += amt;
-		moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
-		t->new_act_mail += moved;
+	if (HASBIT(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) {
+		for (uint i = 0; i < 256; i++) {
+			uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile);
+
+			if (callback == CALLBACK_FAILED) break;
+			if (callback == 0x20FF) break;
+
+			CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grffile);
+			if (cargo == CT_INVALID) continue;
+
+			uint amt = GB(callback, 0, 8);
+			uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt);
+
+			const CargoSpec *cs = GetCargo(cargo);
+			switch (cs->town_effect) {
+				case TE_PASSENGERS:
+					t->new_max_pass += amt;
+					t->new_act_pass += moved;
+					break;
+
+				case TE_MAIL:
+					t->new_max_mail += amt;
+					t->new_act_mail += moved;
+					break;
+
+				default:
+					break;
+			}
+		}
+	} else {
+		if (GB(r, 0, 8) < hs->population) {
+			uint amt = GB(r, 0, 8) / 8 + 1;
+			uint moved;
+
+			if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
+			t->new_max_pass += amt;
+			moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
+			t->new_act_pass += moved;
+		}
+
+		if (GB(r, 8, 8) < hs->mail_generation) {
+			uint amt = GB(r, 8, 8) / 8 + 1;
+			uint moved;
+
+			if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
+			t->new_max_mail += amt;
+			moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
+			t->new_act_mail += moved;
+		}
 	}
 
 	_current_player = OWNER_TOWN;
@@ -424,6 +456,7 @@
 	if (hs->building_flags & BUILDING_HAS_1_TILE &&
 			HASBIT(t->flags12, TOWN_IS_FUNDED) &&
 			CanDeleteHouse(tile) &&
+			max(_cur_year - GetHouseConstructionYear(tile), 0) >= hs->minimum_life &&
 			--t->time_until_rebuild == 0) {
 		t->time_until_rebuild = GB(r, 16, 8) + 192;
 
@@ -488,7 +521,7 @@
 
 	/* Check for custom accepted cargo types */
 	if (HASBIT(hs->callback_mask, CBM_HOUSE_ACCEPT_CARGO)) {
-		uint16 callback = GetHouseCallback(CBID_HOUSE_ACCEPT_CARGO, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback = GetHouseCallback(CBID_HOUSE_ACCEPT_CARGO, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback != CALLBACK_FAILED) {
 			/* Replace accepted cargo types with translated values from callback */
 			accepts[0] = GetCargoTranslation(GB(callback,  0, 5), hs->grffile);
@@ -499,7 +532,7 @@
 
 	/* Check for custom cargo acceptance */
 	if (HASBIT(hs->callback_mask, CBM_CARGO_ACCEPTANCE)) {
-		uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, GetHouseType(tile), GetTownByTile(tile), tile);
+		uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback != CALLBACK_FAILED) {
 			if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4);
 			if (accepts[1] != CT_INVALID) ac[accepts[1]] = GB(callback, 4, 4);
@@ -530,7 +563,7 @@
 	td->owner = OWNER_TOWN;
 }
 
-static uint32 GetTileTrackStatus_Town(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Town(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	/* not used */
 	return 0;
@@ -603,7 +636,7 @@
 
 static RoadBits GetTownRoadMask(TileIndex tile)
 {
-	TrackBits b = GetAnyRoadTrackBits(tile);
+	TrackBits b = GetAnyRoadTrackBits(tile, ROADTYPE_ROAD);
 	RoadBits r = ROAD_NONE;
 
 	if (b & TRACK_BIT_X)     r |= ROAD_X;
@@ -643,7 +676,7 @@
 
 	for (;;) {
 		/* Check if there already is a road at this point? */
-		if (GetAnyRoadTrackBits(tile) == 0) {
+		if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) == 0) {
 			/* No, try to build one in the direction.
 			 * if that fails clear the land, and if that fails exit.
 			 * This is to make sure that we can build a road here later. */
@@ -1177,7 +1210,7 @@
 	/* Let the town be a ghost town
 	 * The player wanted it in such a way. Thus there he has it. ;)
 	 * Never reached in editor mode. */
-	if (_patches.town_layout == TL_NO_ROADS) {
+	if (_patches.town_layout == TL_NO_ROADS && _generating_world) {
 		return false;
 	}
 
@@ -1188,7 +1221,7 @@
 	/* Find a road that we can base the construction on. */
 	tile = t->xy;
 	for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
-		if (GetAnyRoadTrackBits(tile) != 0) {
+		if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) != 0) {
 			int r = GrowTownAtRoad(t, tile);
 			_current_player = old_player;
 			return r != 0;
@@ -1661,7 +1694,7 @@
 				if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue;
 
 				if (HASBIT(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
-					uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, house, t, tile);
+					uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile);
 					if (callback_res != CALLBACK_FAILED && callback_res == 0) continue;
 				}
 			}
@@ -2175,7 +2208,7 @@
 {
 	if (IsTileType(tile, MP_HOUSE) || (
 				IsTileType(tile, MP_STREET) &&
-				(IsLevelCrossing(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile)) == OWNER_TOWN
+				GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN
 			)) {
 		return GetTownByTile(tile);
 	} else {
@@ -2370,19 +2403,19 @@
 /* Save and load the mapping between the house id on the map, and the grf file
  * it came from. */
 static const SaveLoad _house_id_mapping_desc[] = {
-	SLE_VAR(HouseIDMapping, grfid,         SLE_UINT32),
-	SLE_VAR(HouseIDMapping, house_id,      SLE_UINT8),
-	SLE_VAR(HouseIDMapping, substitute_id, SLE_UINT8),
+	SLE_VAR(EntityIDMapping, grfid,         SLE_UINT32),
+	SLE_VAR(EntityIDMapping, entity_id,     SLE_UINT8),
+	SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT8),
 	SLE_END()
 };
 
 static void Save_HOUSEIDS()
 {
-	uint i;
-
-	for (i = 0; i != lengthof(_house_id_mapping); i++) {
+	uint j = _house_mngr.GetMaxMapping();
+
+	for (uint i = 0; i < j; i++) {
 		SlSetArrayIndex(i);
-		SlObject(&_house_id_mapping[i], _house_id_mapping_desc);
+		SlObject(&_house_mngr.mapping_ID[i], _house_id_mapping_desc);
 	}
 }
 
@@ -2390,11 +2423,12 @@
 {
 	int index;
 
-	ResetHouseIDMapping();
+	_house_mngr.ResetMapping();
+	uint max_id = _house_mngr.GetMaxMapping();
 
 	while ((index = SlIterateArray()) != -1) {
-		if ((uint)index >= lengthof(_house_id_mapping)) break;
-		SlObject(&_house_id_mapping[index], _house_id_mapping_desc);
+		if ((uint)index >= max_id) break;
+		SlObject(&_house_mngr.mapping_ID[index], _house_id_mapping_desc);
 	}
 }
 
--- a/src/town_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/town_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -349,7 +349,7 @@
 
 	if (w != NULL) {
 		w->flags4 |= WF_DISABLE_VP_SCROLL;
-		AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetTown(town)->xy, 1);
+		AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetTown(town)->xy, ZOOM_LVL_TOWN);
 	}
 }
 
--- a/src/train_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/train_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -37,6 +37,7 @@
 #include "yapf/yapf.h"
 #include "date.h"
 #include "cargotype.h"
+#include "group.h"
 
 static bool TrainCheckIfLineEnds(Vehicle *v);
 static void TrainController(Vehicle *v, bool update_image);
@@ -166,6 +167,9 @@
 
 		if (IsTrainEngine(u)) first_engine = u->engine_type;
 
+		/* Cache wagon override sprite group. NULL is returned if there is none */
+		u->u.rail.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->u.rail.first_engine);
+
 		if (rvi_u->visual_effect != 0) {
 			u->u.rail.cached_vis_effect = rvi_u->visual_effect;
 		} else {
@@ -217,6 +221,11 @@
 			}
 		}
 
+		if (u->cargo_type == rvi_u->cargo_type && u->cargo_subtype == 0) {
+			/* Set cargo capacity if we've not been refitted */
+			u->cargo_cap = GetVehicleProperty(u, 0x14, rvi_u->capacity);
+		}
+
 		/* check the vehicle length (callback) */
 		uint16 veh_len = CALLBACK_FAILED;
 		if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) {
@@ -632,12 +641,15 @@
 			v->cur_image = 0xAC2;
 			v->random_bits = VehicleRandomBits();
 
+			v->group_id = DEFAULT_GROUP;
+
 			AddArticulatedParts(vl);
 
 			_new_vehicle_id = v->index;
 
 			VehiclePositionChanged(v);
 			TrainConsistChanged(GetFirstVehicleInChain(v));
+			UpdateTrainGroupID(GetFirstVehicleInChain(v));
 
 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 			if (IsLocalPlayer()) {
@@ -792,6 +804,8 @@
 			v->vehicle_flags = 0;
 			if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
+			v->group_id = DEFAULT_GROUP;
+
 			v->subtype = 0;
 			SetFrontEngine(v);
 			SetTrainEngine(v);
@@ -813,6 +827,7 @@
 
 			TrainConsistChanged(v);
 			UpdateTrainAcceleration(v);
+			UpdateTrainGroupID(v);
 
 			if (!HASBIT(p2, 1)) { // check if the cars should be added to the new vehicle
 				NormalizeTrainVehInDepot(v);
@@ -1108,6 +1123,16 @@
 		for (Vehicle *u = src_head; u != NULL; u = u->next) u->first = NULL;
 		for (Vehicle *u = dst_head; u != NULL; u = u->next) u->first = NULL;
 
+		/* If we move the front Engine and if the second vehicle is not an engine
+		   add the whole vehicle to the DEFAULT_GROUP */
+		if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) {
+			const Vehicle *v = GetNextVehicle(src);
+
+			if (v != NULL && !IsTrainEngine(v)) {
+				DoCommand(tile, DEFAULT_GROUP, v->index, flags, CMD_ADD_VEHICLE_GROUP);
+			}
+		}
+
 		if (HASBIT(p2, 0)) {
 			/* unlink ALL wagons */
 			if (src != src_head) {
@@ -1137,6 +1162,14 @@
 					SetFrontEngine(src);
 					assert(src->orders == NULL);
 					src->num_orders = 0;
+
+					// Decrease the engines number of the src engine_type
+					if (!IsDefaultGroupID(src->group_id) && IsValidGroupID(src->group_id)) {
+						GetGroup(src->group_id)->num_engines[src->engine_type]--;
+					}
+
+					// If we move an engine to a new line affect it to the DEFAULT_GROUP
+					src->group_id = DEFAULT_GROUP;
 				}
 			} else {
 				SetFreeWagon(src);
@@ -1198,13 +1231,18 @@
 		 * To do this, CmdMoveRailVehicle must be called once more
 		 * we can't loop forever here because next time we reach this line we will have a front engine */
 		if (src_head != NULL && !IsFrontEngine(src_head) && IsTrainEngine(src_head)) {
+			/* As in CmdMoveRailVehicle src_head->group_id will be equal to DEFAULT_GROUP
+			 * we need to save the group and reaffect it to src_head */
+			const GroupID tmp_g = src_head->group_id;
 			CmdMoveRailVehicle(0, flags, src_head->index | (INVALID_VEHICLE << 16), 1);
+			SetTrainGroupID(src_head, tmp_g);
 			src_head = NULL; // don't do anything more to this train since the new call will do it
 		}
 
 		if (src_head != NULL) {
 			NormaliseTrainConsist(src_head);
 			TrainConsistChanged(src_head);
+			UpdateTrainGroupID(src_head);
 			if (IsFrontEngine(src_head)) {
 				UpdateTrainAcceleration(src_head);
 				InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
@@ -1219,6 +1257,7 @@
 		if (dst_head != NULL) {
 			NormaliseTrainConsist(dst_head);
 			TrainConsistChanged(dst_head);
+			UpdateTrainGroupID(dst_head);
 			if (IsFrontEngine(dst_head)) {
 				UpdateTrainAcceleration(dst_head);
 				InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index);
@@ -1359,6 +1398,8 @@
 					if (first->next_shared != NULL) {
 						first->next_shared->prev_shared = new_f;
 						new_f->next_shared = first->next_shared;
+					} else {
+						RemoveVehicleFromGroup(v);
 					}
 
 					/*
@@ -1389,6 +1430,7 @@
 				if (first != NULL) {
 					NormaliseTrainConsist(first);
 					TrainConsistChanged(first);
+					UpdateTrainGroupID(first);
 					if (IsFrontEngine(first)) {
 						InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
 						InvalidateWindow(WC_VEHICLE_REFIT, first->index);
@@ -1442,6 +1484,7 @@
 					first = UnlinkWagon(v, first);
 					DeleteDepotHighlightOfVehicle(v);
 					DeleteVehicle(v);
+					RemoveVehicleFromGroup(v);
 				}
 			}
 
@@ -1449,6 +1492,7 @@
 			if (flags & DC_EXEC && first != NULL) {
 				NormaliseTrainConsist(first);
 				TrainConsistChanged(first);
+				UpdateTrainGroupID(first);
 				if (IsFrontEngine(first)) UpdateTrainAcceleration(first);
 				InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
 				InvalidateWindow(WC_VEHICLE_REFIT, first->index);
@@ -1893,7 +1937,7 @@
 		Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
 
 		assert(trackdir != INVALID_TRACKDIR);
-		NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
+		NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
 		if (ftd.best_bird_dist == 0) {
 			/* Found target */
 			tfdd.tile = ftd.node.tile;
@@ -2258,7 +2302,7 @@
 		Trackdir trackdir = GetVehicleTrackdir(v);
 		assert(trackdir != 0xff);
 
-		NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
+		NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
 
 		if (ftd.best_trackdir == 0xff) {
 			/* We are already at our target. Just do something
@@ -2368,7 +2412,7 @@
 		assert(trackdir != 0xff);
 		assert(trackdir_rev != 0xff);
 
-		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
+		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
 		if (ftd.best_bird_dist != 0) {
 			/* We didn't find anything, just keep on going straight ahead */
 			reverse_best = false;
@@ -2876,7 +2920,7 @@
 
 				/* Get the status of the tracks in the new tile and mask
 				 * away the bits that aren't reachable. */
-				uint32 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _reachable_tracks[enterdir];
+				uint32 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0) & _reachable_tracks[enterdir];
 
 				/* Combine the from & to directions.
 				 * Now, the lower byte contains the track status, and the byte at bit 16 contains
@@ -3058,6 +3102,9 @@
 
 	BeginVehicleMove(v);
 	EndVehicleMove(v);
+
+	if (IsFrontEngine(v)) RemoveVehicleFromGroup(v);
+
 	DeleteVehicle(v);
 
 	if (v->u.rail.track != TRACK_BIT_DEPOT && v->u.rail.track != TRACK_BIT_WORMHOLE)
@@ -3143,6 +3190,7 @@
 
 	if (state >= 4440 && !(v->tick_counter&0x1F)) {
 		DeleteLastWagon(v);
+		InvalidateWindow(WC_REPLACE_VEHICLE, (v->group_id << 16) | VEH_TRAIN);
 	}
 }
 
@@ -3217,7 +3265,7 @@
 	/* Calculate next tile */
 	tile += TileOffsByDiagDir(dir);
 	// determine the track status on the next tile.
-	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL) & _reachable_tracks[dir];
+	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir];
 
 	/* Calc position within the current tile ?? */
 	uint x = v->x_pos & 0xF;
--- a/src/train_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/train_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -320,7 +320,7 @@
 
 	if (w != NULL) {
 		w->caption_color = v->owner;
-		AssignWindowViewport(w, 3, 17, 0xE2, 0x66, w->window_number | (1 << 31), 0);
+		AssignWindowViewport(w, 3, 17, 0xE2, 0x66, w->window_number | (1 << 31), ZOOM_LVL_TRAIN);
 	}
 }
 
--- a/src/tree_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/tree_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -648,7 +648,7 @@
 	/* not used */
 }
 
-static uint32 GetTileTrackStatus_Trees(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Trees(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	return 0;
 }
--- a/src/tunnel_map.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/tunnel_map.h	Fri May 25 00:25:08 2007 +0000
@@ -9,6 +9,7 @@
 #include "macros.h"
 #include "map.h"
 #include "rail.h"
+#include "road.h"
 
 /**
  * Is this a tunnel (entrance)?
@@ -93,13 +94,14 @@
  * @param t the entrance of the tunnel
  * @param o the owner of the entrance
  * @param d the direction facing out of the tunnel
+ * @param r the road type used in the tunnel
  */
-static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d)
+static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r)
 {
 	SetTileType(t, MP_TUNNELBRIDGE);
 	SetTileOwner(t, o);
 	_m[t].m2 = 0;
-	_m[t].m3 = 0;
+	_m[t].m3 = r;
 	_m[t].m4 = 0;
 	_m[t].m5 = TRANSPORT_ROAD << 2 | d;
 }
--- a/src/tunnelbridge_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -172,12 +172,14 @@
  * @param p1 packed start tile coords (~ dx)
  * @param p2 various bitstuffed elements
  * - p2 = (bit 0- 7) - bridge type (hi bh)
- * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge.
+ * - p2 = (bit 8-..) - rail type or road types.
+ * - p2 = (bit 15  ) - set means road bridge.
  */
 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	uint bridge_type;
 	RailType railtype;
+	RoadTypes roadtypes;
 	uint x;
 	uint y;
 	uint sx;
@@ -207,9 +209,12 @@
 	/* type of bridge */
 	if (HASBIT(p2, 15)) {
 		railtype = INVALID_RAILTYPE; // road bridge
+		roadtypes = (RoadTypes)GB(p2, 8, 3);
+		if (!AreValidRoadTypes(roadtypes)) return CMD_ERROR;
 	} else {
 		if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR;
 		railtype = (RailType)GB(p2, 8, 8);
+		roadtypes = ROADTYPES_NONE;
 	}
 
 	x = TileX(end_tile);
@@ -351,8 +356,8 @@
 			MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
 			MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
 		} else {
-			MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir);
-			MakeRoadBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir));
+			MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes);
+			MakeRoadBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), roadtypes);
 		}
 		MarkTileDirtyByTile(tile_start);
 		MarkTileDirtyByTile(tile_end);
@@ -441,7 +446,7 @@
 /** Build Tunnel.
  * @param start_tile start tile of tunnel
  * @param flags type of operation
- * @param p1 railtype, 0x200 for road tunnel
+ * @param p1 railtype or roadtypes. bit 9 set means road tunnel
  * @param p2 unused
  */
 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
@@ -457,8 +462,11 @@
 	int32 ret;
 
 	_build_tunnel_endtile = 0;
-
-	if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
+	if (!HASBIT(p1, 9)) {
+		if (!ValParamRailtype(p1)) return CMD_ERROR;
+	} else if (!AreValidRoadTypes((RoadTypes)GB(p1, 0, 3))) {
+		return CMD_ERROR;
+	}
 
 	start_tileh = GetTileSlope(start_tile, &start_z);
 
@@ -518,8 +526,8 @@
 			UpdateSignalsOnSegment(start_tile, direction);
 			YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction)));
 		} else {
-			MakeRoadTunnel(start_tile, _current_player, direction);
-			MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction));
+			MakeRoadTunnel(start_tile, _current_player, direction,                 (RoadTypes)GB(p1, 0, 3));
+			MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3));
 		}
 	}
 
@@ -878,9 +886,11 @@
 
 		image += GetTunnelDirection(ti->tile) * 2;
 		DrawGroundSprite(image, PAL_NONE);
-		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL && GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
+			DrawCatenary(ti);
+		}
 
-		AddSortableSpriteToDraw(image+1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
+		AddSortableSpriteToDraw(image + 1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, 1, 1, 8, (byte)ti->z);
 		DrawBridgeMiddle(ti);
 	} else if (IsBridge(ti->tile)) { // XXX is this necessary?
 		const PalSpriteID *psid;
@@ -916,7 +926,9 @@
 			DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE);
 		}
 
-		if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti);
+		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL && GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
+			DrawCatenary(ti);
+		}
 
 		image = psid->sprite;
 
@@ -1223,13 +1235,15 @@
 }
 
 
-static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	if (IsTunnel(tile)) {
 		if (GetTunnelTransportType(tile) != mode) return 0;
+		if (GetTunnelTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
 		return AxisToTrackBits(DiagDirToAxis(GetTunnelDirection(tile))) * 0x101;
 	} else {
 		if (GetBridgeTransportType(tile) != mode) return 0;
+		if (GetBridgeTransportType(tile) == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0) return 0;
 		return AxisToTrackBits(DiagDirToAxis(GetBridgeRampDirection(tile))) * 0x101;
 	}
 }
--- a/src/unix.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/unix.cpp	Fri May 25 00:25:08 2007 +0000
@@ -53,7 +53,7 @@
 #else
 	/* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
 	const char *s = strchr(path, ':');
-	return s[1] == '\0';
+	return s != NULL && s[1] == '\0';
 #endif
 }
 
--- a/src/unmovable_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/unmovable_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -319,7 +319,7 @@
 }
 
 
-static uint32 GetTileTrackStatus_Unmovable(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Unmovable(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	return 0;
 }
--- a/src/variables.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/variables.h	Fri May 25 00:25:08 2007 +0000
@@ -78,7 +78,6 @@
 /* Keep track of current game position */
 VARDEF int _saved_scrollpos_x;
 VARDEF int _saved_scrollpos_y;
-VARDEF byte _saved_scrollpos_zoom;
 
 /* ********* END OF SAVE REGION */
 
@@ -119,6 +118,7 @@
 	byte se_flat_world_height;          // land height a flat world gets in SE
 	bool bribe;                         // enable bribing the local authority
 	bool nonuniform_stations;           // allow nonuniform train stations
+	bool adjacent_stations;             // allow stations to be built directly adjacent to other stations
 	bool always_small_airport;          // always allow small airports
 	bool realistic_acceleration;        // realistic acceleration for trains
 	bool wagon_speed_limits;            // enable wagon speed limits
@@ -131,6 +131,7 @@
 	bool measure_tooltip;               // Show a permanent tooltip when dragging tools
 	byte liveries;                      // Options for displaying company liveries, 0=none, 1=self, 2=all
 	bool prefer_teamchat;               // Choose the chat message target with <ENTER>, true=all players, false=your team
+	bool advanced_vehicle_list;         // Use the "advanced" vehicle list
 
 	uint8 toolbar_pos;                  // position of toolbars, 0=left, 1=center, 2=right
 	uint8 window_snap_radius;           // Windows snap at each other if closer than this
--- a/src/vehicle.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/vehicle.cpp	Fri May 25 00:25:08 2007 +0000
@@ -40,6 +40,7 @@
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
 #include "helpers.hpp"
+#include "group.h"
 #include "economy.h"
 
 #define INVALID_COORD (-0x8000)
@@ -111,7 +112,7 @@
 		return false; // Crashed vehicles don't need service anymore
 
 	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
-		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
+		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type, v->group_id);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
 	}
 
 	return _patches.servint_ispercent ?
@@ -238,8 +239,13 @@
 
 	FOR_ALL_VEHICLES(v) {
 		switch (v->type) {
+			case VEH_ROAD:
+				v->cur_image = GetRoadVehImage(v, v->direction);
+				v->u.road.roadtype = ROADTYPE_ROAD;
+				v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
+				break;
+
 			case VEH_TRAIN: v->cur_image = GetTrainImage(v, v->direction); break;
-			case VEH_ROAD: v->cur_image = GetRoadVehImage(v, v->direction); break;
 			case VEH_SHIP: v->cur_image = GetShipImage(v, v->direction); break;
 			case VEH_AIRCRAFT:
 				if (IsNormalAircraft(v)) {
@@ -284,6 +290,8 @@
 	v->prev_shared = NULL;
 	v->depot_list  = NULL;
 	v->random_bits = 0;
+	v->group_id = DEFAULT_GROUP;
+
 	return v;
 }
 
@@ -580,6 +588,9 @@
 	if (IsEngineCountable(v)) {
 		GetPlayer(v->owner)->num_engines[v->engine_type]--;
 		if (v->owner == _local_player) InvalidateAutoreplaceWindow(v->engine_type);
+
+		if (IsValidGroupID(v->group_id)) GetGroup(v->group_id)->num_engines[v->engine_type]--;
+		if (v->type != VEH_TRAIN || IsFrontEngine(v)) DecreaseGroupNumVehicle(v->group_id);
 	}
 
 	DeleteVehicleNews(v->index, INVALID_STRING_ID);
@@ -659,8 +670,6 @@
 
 void CallVehicleTicks()
 {
-	Vehicle *v;
-
 #ifdef ENABLE_NETWORK
 	/* hotfix for desync problem:
 	 *  for MP games invalidate the YAPF cache every tick to keep it exactly the same on the server and all clients */
@@ -671,10 +680,16 @@
 
 	_first_veh_in_depot_list = NULL; // now we are sure it's initialized at the start of each tick
 
+	Station *st;
+	FOR_ALL_STATIONS(st) LoadUnloadStation(st);
+
+	Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
 		_vehicle_tick_procs[v->type](v);
 
 		switch (v->type) {
+			default: break;
+
 			case VEH_TRAIN:
 			case VEH_ROAD:
 			case VEH_AIRCRAFT:
@@ -1421,8 +1436,8 @@
 			 (uint)(y -= vp->top) >= (uint)vp->height)
 				return NULL;
 
-	x = (x << vp->zoom) + vp->virtual_left;
-	y = (y << vp->zoom) + vp->virtual_top;
+	x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
+	y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
 
 	FOR_ALL_VEHICLES(v) {
 		if ((v->vehstatus & (VS_HIDDEN|VS_UNCLICKABLE)) == 0 &&
@@ -1562,7 +1577,7 @@
 	int32 return_value = CMD_ERROR;
 	uint i;
 	uint stop_command;
-	byte vehicle_type = GB(p2, 0, 5);
+	VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
 	bool start_stop = HASBIT(p2, 5);
 	bool vehicle_list_window = HASBIT(p2, 6);
 
@@ -1629,7 +1644,7 @@
 
 	int32 cost = 0;
 	uint i, sell_command, total_number_vehicles;
-	byte vehicle_type = GB(p1, 0, 8);
+	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 
 	switch (vehicle_type) {
 		case VEH_TRAIN:    sell_command = CMD_SELL_RAIL_WAGON; break;
@@ -1678,8 +1693,7 @@
 	uint16 engine_count = 0;
 	uint i, x = 0, y = 0, z = 0;
 	int32 cost = 0;
-	byte vehicle_type = GB(p1, 0, 8);
-
+	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 
 	if (!IsTileOwner(tile, _current_player)) return CMD_ERROR;
 
@@ -1818,6 +1832,12 @@
 		_new_vehicle_id = w_front->index;
 	}
 
+	if (flags & DC_EXEC) {
+		/* Cloned vehicles belong to the same group */
+		DoCommand(0, v_front->group_id, w_front->index, flags, CMD_ADD_VEHICLE_GROUP);
+	}
+
+
 	/* Take care of refitting. */
 	w = w_front;
 	v = v_front;
@@ -1891,7 +1911,7 @@
  * @param *wagon_list_length Allocated size of wagon_list. Needs to be set to 0 when wagon_list points to a NULL array
  * @param *wagon_count The number of engines stored in the list
  */
-void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count)
+void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count)
 {
 	Vehicle *v;
 
@@ -1970,11 +1990,12 @@
       <li>VLW_SHARED_ORDERS: index of order to generate a list for<li>
       <li>VLW_STANDARD: not used<li>
       <li>VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for</li>
+      <li>VLW_GROUP_LIST: index of group to generate a list for</li>
     </ul>
 * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
 * @return the number of vehicles added to the list
 */
-uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type)
+uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type)
 {
 	const byte subtype = (type != VEH_AIRCRAFT) ? (byte)Train_Front : (byte)AIR_AIRCRAFT;
 	uint n = 0;
@@ -2048,6 +2069,19 @@
 			break;
 		}
 
+ 		case VLW_GROUP_LIST:
+			FOR_ALL_VEHICLES(v) {
+				if (v->type == type && (
+							(type == VEH_TRAIN && IsFrontEngine(v)) ||
+							(type != VEH_TRAIN && v->subtype <= subtype)
+						) && v->owner == owner && v->group_id == index) {
+					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4);
+
+					(*sort_list)[n++] = v;
+				}
+			}
+			break;
+
 		default: NOT_REACHED(); break;
 	}
 
@@ -2071,7 +2105,7 @@
  * @param vlw_flag tells what kind of list requested the goto depot
  * @return 0 for success and CMD_ERROR if no vehicle is able to go to depot
  */
-int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
+int32 SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
 {
 	const Vehicle **sort_list = NULL;
 	uint n, i;
@@ -2381,7 +2415,7 @@
 	return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
 }
 
-UnitID GetFreeUnitNumber(byte type)
+UnitID GetFreeUnitNumber(VehicleType type)
 {
 	UnitID unit, max = 0;
 	const Vehicle *u;
@@ -2439,6 +2473,7 @@
 	if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) {
 		/* Determine the livery scheme to use */
 		switch (GetEngine(engine_type)->type) {
+			default: NOT_REACHED();
 			case VEH_TRAIN: {
 				const RailVehicleInfo *rvi = RailVehInfo(engine_type);
 
@@ -2449,7 +2484,7 @@
 					{
 						if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type;
 						if (rvi->railveh_type == RAILVEH_WAGON) {
-							if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL || cargo_type == CT_VALUABLES) {
+							if (!GetCargo(cargo_type)->is_freight) {
 								if (parent_engine_type == INVALID_ENGINE) {
 									scheme = LS_PASSENGER_WAGON_STEAM;
 								} else {
@@ -2663,6 +2698,8 @@
 	    SLE_REF(Vehicle, next_shared,          REF_VEHICLE),
 	    SLE_REF(Vehicle, prev_shared,          REF_VEHICLE),
 
+	SLE_CONDVAR(Vehicle, group_id,             SLE_UINT16,                60, SL_MAX_VERSION),
+
 	/* reserve extra space in savegame here. (currently 10 bytes) */
 	SLE_CONDNULL(10,                                                       2, SL_MAX_VERSION),
 
@@ -2848,6 +2885,7 @@
 			case VEH_SPECIAL:  v = new (v) SpecialVehicle();  break;
 			case VEH_DISASTER: v = new (v) DisasterVehicle(); break;
 			case VEH_INVALID:  v = new (v) InvalidVehicle();  break;
+			default: NOT_REACHED();
 		}
 
 		/* Old savegames used 'last_station_visited = 0xFF' */
@@ -2860,6 +2898,9 @@
 			v->current_order.flags = (v->current_order.type & 0xF0) >> 4;
 			v->current_order.type.m_val &= 0x0F;
 		}
+
+		/* Advanced vehicle lists got added */
+		if (CheckSavegameVersion(60)) v->group_id = DEFAULT_GROUP;
 	}
 
 	/* Check for shared order-lists (we now use pointers for that) */
@@ -2933,15 +2974,8 @@
 {
 	switch (this->current_order.type) {
 		case OT_LOADING: {
-			/* Not the first call for this tick */
-			if (mode) return;
-
-			/* We have not waited enough time till the next round of loading/unloading */
-			if (--this->load_unload_time_rem) return;
-
-			/* Load/unload the vehicle; when it actually did something
-			 * we do not leave the station. */
-			if (LoadUnloadVehicle(this)) return;
+			/* Not the first call for this tick, or still loading */
+			if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED)) return;
 
 			this->PlayLeaveStationSound();
 
--- a/src/vehicle.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/vehicle.h	Fri May 25 00:25:08 2007 +0000
@@ -8,6 +8,7 @@
 #include "oldpool.h"
 #include "order.h"
 #include "rail.h"
+#include "road.h"
 
 /** The returned bits of VehicleEnterTile. */
 enum VehicleEnterTileStatus {
@@ -64,15 +65,18 @@
 	RVSB_ROAD_STOP_TRACKDIR_MASK = 0x09                       ///< Only bits 0 and 3 are used to encode the trackdir for road stops
 };
 
-enum {
+enum VehicleType {
 	VEH_TRAIN,
 	VEH_ROAD,
 	VEH_SHIP,
 	VEH_AIRCRAFT,
 	VEH_SPECIAL,
 	VEH_DISASTER,
+	VEH_END,
 	VEH_INVALID = 0xFF,
-} ;
+};
+template <> struct EnumPropsT<VehicleType> : MakeEnumPropsT<VehicleType, byte, VEH_TRAIN, VEH_END, VEH_INVALID> {};
+typedef TinyEnumT<VehicleType> VehicleTypeByte;
 
 enum VehStatus {
 	VS_HIDDEN          = 0x01,
@@ -141,6 +145,9 @@
 
 	/* Link between the two ends of a multiheaded engine */
 	Vehicle *other_multiheaded_part;
+
+	/* Cached wagon override spritegroup */
+	const struct SpriteGroup *cached_override;
 };
 
 enum {
@@ -182,6 +189,9 @@
 	byte reverse_ctr;
 	struct RoadStop *slot;
 	byte slot_age;
+
+	RoadType roadtype;
+	RoadTypes compatible_roadtypes;
 };
 
 struct VehicleSpecial {
@@ -200,7 +210,7 @@
 
 
 struct Vehicle {
-	byte type;               // type, ie roadven,train,ship,aircraft,special
+	VehicleTypeByte type;    ///< Type of vehicle
 	byte subtype;            // subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes)
 
 	VehicleID index;         // NOSAVE: Index in vehicle array
@@ -304,6 +314,8 @@
 	TileIndex cargo_loaded_at_xy;  ///< tile index where feeder cargo was loaded
 	uint32 value;
 
+	GroupID group_id;              ///< Index of group Pool array
+
 	union {
 		VehicleRail rail;
 		VehicleAir air;
@@ -516,9 +528,7 @@
 
 void ShowAircraftViewWindow(const Vehicle* v);
 
-UnitID GetFreeUnitNumber(byte type);
-
-bool LoadUnloadVehicle(Vehicle *v);
+UnitID GetFreeUnitNumber(VehicleType type);
 
 void TrainConsistChanged(Vehicle *v);
 void TrainPowerChanged(Vehicle *v);
@@ -528,9 +538,9 @@
 
 bool VehicleNeedsService(const Vehicle *v);
 
-uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type);
-void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count);
-int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
+uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type);
+void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count);
+int32 SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
 bool IsVehicleInDepot(const Vehicle *v);
 void VehicleEnterDepot(Vehicle *v);
 
@@ -606,7 +616,7 @@
 	v = new (v) InvalidVehicle();
 }
 
-static inline bool IsPlayerBuildableVehicleType(byte type)
+static inline bool IsPlayerBuildableVehicleType(VehicleType type)
 {
 	switch (type) {
 		case VEH_TRAIN:
@@ -614,8 +624,9 @@
 		case VEH_SHIP:
 		case VEH_AIRCRAFT:
 			return true;
+
+		default: return false;
 	}
-	return false;
 }
 
 static inline bool IsPlayerBuildableVehicleType(const Vehicle *v)
@@ -711,7 +722,7 @@
 extern const uint32 _send_to_depot_proc_table[];
 
 /* Functions to find the right command for certain vehicle type */
-static inline uint32 GetCmdBuildVeh(byte type)
+static inline uint32 GetCmdBuildVeh(VehicleType type)
 {
 	return _veh_build_proc_table[type];
 }
@@ -721,7 +732,7 @@
 	return GetCmdBuildVeh(v->type);
 }
 
-static inline uint32 GetCmdSellVeh(byte type)
+static inline uint32 GetCmdSellVeh(VehicleType type)
 {
 	return _veh_sell_proc_table[type];
 }
@@ -731,7 +742,7 @@
 	return GetCmdSellVeh(v->type);
 }
 
-static inline uint32 GetCmdRefitVeh(byte type)
+static inline uint32 GetCmdRefitVeh(VehicleType type)
 {
 	return _veh_refit_proc_table[type];
 }
@@ -741,7 +752,7 @@
 	return GetCmdRefitVeh(v->type);
 }
 
-static inline uint32 GetCmdSendToDepot(byte type)
+static inline uint32 GetCmdSendToDepot(VehicleType type)
 {
 	return _send_to_depot_proc_table[type];
 }
--- a/src/vehicle_gui.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/vehicle_gui.cpp	Fri May 25 00:25:08 2007 +0000
@@ -31,6 +31,7 @@
 #include "depot.h"
 #include "helpers.hpp"
 #include "cargotype.h"
+#include "group.h"
 
 struct Sorting {
 	Listing aircraft;
@@ -41,15 +42,6 @@
 
 static Sorting _sorting;
 
-struct vehiclelist_d {
-	const Vehicle** sort_list;  // List of vehicles (sorted)
-	Listing *_sorting;          // pointer to the appropiate subcategory of _sorting
-	uint16 length_of_sort_list; // Keeps track of how many vehicle pointers sort list got space for
-	byte vehicle_type;          // The vehicle type that is sorted
-	list_d l;                   // General list struct
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d));
-
 static bool   _internal_sort_order;     // descending/ascending
 
 typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
@@ -78,7 +70,7 @@
 	&VehicleValueSorter,
 };
 
-static const StringID _vehicle_sort_listing[] = {
+const StringID _vehicle_sort_listing[] = {
 	STR_SORT_BY_NUMBER,
 	STR_SORT_BY_DROPDOWN_NAME,
 	STR_SORT_BY_AGE,
@@ -134,7 +126,7 @@
 	}
 }
 
-static void BuildVehicleList(vehiclelist_d* vl, PlayerID owner, uint16 index, uint16 window_type)
+void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type)
 {
 	if (!(vl->l.flags & VL_REBUILD)) return;
 
@@ -146,7 +138,7 @@
 	vl->l.flags |= VL_RESORT;
 }
 
-static void SortVehicleList(vehiclelist_d *vl)
+void SortVehicleList(vehiclelist_d *vl)
 {
 	if (!(vl->l.flags & VL_RESORT)) return;
 
@@ -377,6 +369,7 @@
 							int command = 0;
 
 							switch (v->type) {
+								default: NOT_REACHED();
 								case VEH_TRAIN:    command = CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE);  break;
 								case VEH_ROAD:     command = CMD_REFIT_ROAD_VEH     | CMD_MSG(STR_REFIT_ROAD_VEHICLE_CAN_T);  break;
 								case VEH_SHIP:     command = CMD_REFIT_SHIP         | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP);     break;
@@ -748,16 +741,6 @@
 	}
 }
 
-/*
- * Start of functions regarding vehicle list windows
- */
-
-enum {
-	PLY_WND_PRC__OFFSET_TOP_WIDGET = 26,
-	PLY_WND_PRC__SIZE_OF_ROW_SMALL = 26,
-	PLY_WND_PRC__SIZE_OF_ROW_BIG   = 36,
-};
-
 enum VehicleListWindowWidgets {
 	VLW_WIDGET_CLOSEBOX = 0,
 	VLW_WIDGET_CAPTION,
@@ -808,7 +791,7 @@
 	uint16 window_type = w->window_number & VLW_MASK;
 	PlayerID player = (PlayerID)GB(w->window_number, 0, 8);
 
-	vl->vehicle_type = GB(w->window_number, 11, 5);
+	vl->vehicle_type = (VehicleType)GB(w->window_number, 11, 5);
 	vl->length_of_sort_list = 0;
 	vl->sort_list = NULL;
 	w->caption_color = player;
@@ -925,7 +908,7 @@
 	vl->l.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer
 }
 
-static void DrawSmallOrderList(const Vehicle *v, int x, int y)
+void DrawSmallOrderList(const Vehicle *v, int x, int y)
 {
 	const Order *order;
 	int sel, i = 0;
@@ -1235,7 +1218,7 @@
 	PlayerVehWndProc
 };
 
-static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, byte vehicle_type, uint16 unique_number)
+static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, VehicleType vehicle_type, uint16 unique_number)
 {
 	Window *w;
 	WindowNumber num;
@@ -1272,9 +1255,13 @@
 	}
 }
 
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type)
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type)
 {
-	ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0);
+	if (player == _local_player && _patches.advanced_vehicle_list) {
+		ShowPlayerGroup(player, vehicle_type);
+	} else {
+		ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0);
+	}
 }
 
 void ShowVehicleListWindow(const Vehicle *v)
@@ -1283,12 +1270,12 @@
 	ShowVehicleListWindowLocal(v->owner, VLW_SHARED_ORDERS, v->type, v->orders->index);
 }
 
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type, StationID station)
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, StationID station)
 {
 	ShowVehicleListWindowLocal(player, VLW_STATION_LIST, vehicle_type, station);
 }
 
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type, TileIndex depot_tile)
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, TileIndex depot_tile)
 {
 	uint16 depot_airport_index;
 
--- a/src/vehicle_gui.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/vehicle_gui.h	Fri May 25 00:25:08 2007 +0000
@@ -15,21 +15,35 @@
 /* sorter stuff */
 void RebuildVehicleLists();
 void ResortVehicleLists();
+void SortVehicleList(vehiclelist_d *vl);
+void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type);
 
 #define PERIODIC_RESORT_DAYS 10
 
+extern const StringID _vehicle_sort_listing[];
+
+/* Start of functions regarding vehicle list windows */
+enum {
+	PLY_WND_PRC__OFFSET_TOP_WIDGET = 26,
+	PLY_WND_PRC__SIZE_OF_ROW_TINY  = 13,
+	PLY_WND_PRC__SIZE_OF_ROW_SMALL = 26,
+	PLY_WND_PRC__SIZE_OF_ROW_BIG   = 36,
+	PLY_WND_PRC__SIZE_OF_ROW_BIG2  = 39,
+};
+
 /* Vehicle List Window type flags */
 enum {
 	VLW_STANDARD      = 0 << 8,
 	VLW_SHARED_ORDERS = 1 << 8,
 	VLW_STATION_LIST  = 2 << 8,
 	VLW_DEPOT_LIST    = 3 << 8,
+	VLW_GROUP_LIST    = 4 << 8,
 	VLW_MASK          = 0x700,
 };
 
 static inline bool ValidVLWFlags(uint16 flags)
 {
-	return (flags == VLW_STANDARD || flags == VLW_SHARED_ORDERS || flags == VLW_STATION_LIST || flags == VLW_DEPOT_LIST);
+	return (flags == VLW_STANDARD || flags == VLW_SHARED_ORDERS || flags == VLW_STATION_LIST || flags == VLW_DEPOT_LIST || flags == VLW_GROUP_LIST);
 }
 
 void PlayerVehWndProc(Window *w, WindowEvent *e);
@@ -41,7 +55,7 @@
 void DrawShipImage(const Vehicle *v, int x, int y, VehicleID selection);
 void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection);
 
-void ShowBuildVehicleWindow(TileIndex tile, byte type);
+void ShowBuildVehicleWindow(TileIndex tile, VehicleType type);
 
 void ChangeVehicleViewWindow(const Vehicle *from_v, const Vehicle *to_v);
 
@@ -49,11 +63,13 @@
 uint ShowRefitOptionsList(int x, int y, uint w, EngineID engine);
 
 void ShowVehicleListWindow(const Vehicle *v);
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type);
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type, StationID station);
-void ShowVehicleListWindow(PlayerID player, byte vehicle_type, TileIndex depot_tile);
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type);
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, StationID station);
+void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type, TileIndex depot_tile);
 
-void ShowReplaceVehicleWindow(byte vehicletype);
+void ShowReplaceVehicleWindow(VehicleType vehicletype);
+void DrawSmallOrderList(const Vehicle *v, int x, int y);
+void ShowReplaceGroupVehicleWindow(GroupID group, VehicleType veh);
 
 static inline void DrawVehicleImage(const Vehicle *v, int x, int y, int count, int skip, VehicleID selection)
 {
@@ -66,7 +82,7 @@
 	}
 }
 
-static inline uint GetVehicleListHeight(byte type)
+static inline uint GetVehicleListHeight(VehicleType type)
 {
 	return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24;
 }
--- a/src/video/dedicated_v.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/video/dedicated_v.cpp	Fri May 25 00:25:08 2007 +0000
@@ -112,7 +112,7 @@
 #endif
 
 
-static void *_dedicated_video_mem;
+static Pixel *_dedicated_video_mem;
 
 extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
 extern void SwitchMode(int new_mode);
@@ -122,7 +122,7 @@
 {
 	_screen.width = _screen.pitch = _cur_resolution[0];
 	_screen.height = _cur_resolution[1];
-	_dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
+	_dedicated_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel));
 
 	SetDebugString("net=6");
 
@@ -283,7 +283,7 @@
 			next_tick = cur_ticks + 30;
 
 			GameLoop();
-			_screen.dst_ptr = (Pixel*)_dedicated_video_mem;
+			_screen.dst_ptr = _dedicated_video_mem;
 			UpdateWindows();
 		}
 		CSleep(1);
--- a/src/video/null_v.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/video/null_v.cpp	Fri May 25 00:25:08 2007 +0000
@@ -7,13 +7,13 @@
 #include "../window.h"
 #include "null_v.h"
 
-static void* _null_video_mem = NULL;
+static Pixel *_null_video_mem = NULL;
 
 static const char* NullVideoStart(const char* const* parm)
 {
 	_screen.width = _screen.pitch = _cur_resolution[0];
 	_screen.height = _cur_resolution[1];
-	_null_video_mem = malloc(_cur_resolution[0] * _cur_resolution[1]);
+	_null_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel));
 	return NULL;
 }
 
@@ -27,7 +27,7 @@
 
 	for (i = 0; i < 1000; i++) {
 		GameLoop();
-		_screen.dst_ptr = (Pixel*)_null_video_mem;
+		_screen.dst_ptr = _null_video_mem;
 		UpdateWindows();
 	}
 }
--- a/src/video/sdl_v.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/video/sdl_v.cpp	Fri May 25 00:25:08 2007 +0000
@@ -195,7 +195,7 @@
 
 	_screen.width = newscreen->w;
 	_screen.height = newscreen->h;
-	_screen.pitch = newscreen->pitch;
+	_screen.pitch = newscreen->pitch / sizeof(Pixel);
 
 	_sdl_screen = newscreen;
 	InitPalette();
--- a/src/video/win32_v.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/video/win32_v.cpp	Fri May 25 00:25:08 2007 +0000
@@ -671,7 +671,7 @@
 
 	if (_wnd.double_size) {
 		w = ALIGN(w, 4);
-		_wnd.alloced_bits = _wnd.buffer_bits = (Pixel*)malloc(w * h);
+		_wnd.alloced_bits = _wnd.buffer_bits = (Pixel *)malloc(w * h * sizeof(Pixel));
 		w *= 2;
 		h *= 2;
 	}
--- a/src/viewport.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/viewport.cpp	Fri May 25 00:25:08 2007 +0000
@@ -26,6 +26,8 @@
 
 #define VIEWPORT_DRAW_MEM (65536 * 2)
 
+ZoomLevel _saved_scrollpos_zoom;
+
 /* XXX - maximum viewports is maximum windows - 2 (main toolbar + status bar) */
 static ViewPort _viewports[25 - 2];
 static uint32 _active_viewports;    ///< bitmasked variable where each bit signifies if a viewport is in use or not
@@ -143,7 +145,7 @@
 }
 
 void AssignWindowViewport(Window *w, int x, int y,
-	int width, int height, uint32 follow_flags, byte zoom)
+	int width, int height, uint32 follow_flags, ZoomLevel zoom)
 {
 	ViewPort *vp;
 	Point pt;
@@ -162,8 +164,8 @@
 
 	vp->zoom = zoom;
 
-	vp->virtual_width = width << zoom;
-	vp->virtual_height = height << zoom;
+	vp->virtual_width = ScaleByZoom(width, zoom);
+	vp->virtual_height = ScaleByZoom(height, zoom);
 
 	if (follow_flags & 0x80000000) {
 		const Vehicle *veh;
@@ -267,10 +269,10 @@
 	vp->virtual_left = x;
 	vp->virtual_top = y;
 
-	old_left >>= vp->zoom;
-	old_top >>= vp->zoom;
-	x >>= vp->zoom;
-	y >>= vp->zoom;
+	old_left = UnScaleByZoom(old_left, vp->zoom);
+	old_top = UnScaleByZoom(old_top, vp->zoom);
+	x = UnScaleByZoom(x, vp->zoom);
+	y = UnScaleByZoom(y, vp->zoom);
 
 	old_left -= x;
 	old_top -= y;
@@ -331,8 +333,8 @@
 				return pt;
 	}
 
-	x = ((x << vp->zoom) + vp->virtual_left) >> 2;
-	y = ((y << vp->zoom) + vp->virtual_top) >> 1;
+	x = (ScaleByZoom(x, vp->zoom) + vp->virtual_left) >> 2;
+	y = (ScaleByZoom(y, vp->zoom) + vp->virtual_top) >> 1;
 
 	a = y-x;
 	b = y+x;
@@ -404,10 +406,10 @@
  * @param widget_zoom_out widget index for window with zoom-out button */
 void HandleZoomMessage(Window *w, const ViewPort *vp, byte widget_zoom_in, byte widget_zoom_out)
 {
-	SetWindowWidgetDisabledState(w, widget_zoom_in, vp->zoom == 0);
+	SetWindowWidgetDisabledState(w, widget_zoom_in, vp->zoom == ZOOM_LVL_MIN);
 	InvalidateWidget(w, widget_zoom_in);
 
-	SetWindowWidgetDisabledState(w, widget_zoom_out, vp->zoom == 2);
+	SetWindowWidgetDisabledState(w, widget_zoom_out, vp->zoom == ZOOM_LVL_MAX);
 	InvalidateWidget(w, widget_zoom_out);
 }
 
@@ -669,7 +671,7 @@
 				z += TILE_HEIGHT;
 				if (ti->tileh == SLOPE_STEEP_N) z += TILE_HEIGHT;
 			}
-			DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z);
+			DrawGroundSpriteAt(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z);
 		} else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) {
 			/* autorail highlight piece under cursor */
 			uint type = _thd.drawstyle & 0xF;
@@ -808,7 +810,7 @@
 	bottom = top + dpi->height;
 
 	switch (dpi->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			FOR_ALL_TOWNS(t) {
 				if (bottom > t->sign.top &&
 						top    < t->sign.top + 12 &&
@@ -821,7 +823,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			right += 2;
 			bottom += 2;
 
@@ -837,21 +839,26 @@
 			}
 			break;
 
-		default: NOT_REACHED();
-		case 2:
-			right += 4;
-			bottom += 5;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			right += ScaleByZoom(1, dpi->zoom);
+			bottom += ScaleByZoom(1, dpi->zoom) + 1;
 
 			FOR_ALL_TOWNS(t) {
 				if (bottom > t->sign.top &&
-						top    < t->sign.top + 24 &&
+						top    < t->sign.top + ScaleByZoom(12, dpi->zoom) &&
 						right  > t->sign.left &&
-						left   < t->sign.left + t->sign.width_2*4) {
+						left   < t->sign.left + ScaleByZoom(t->sign.width_2, dpi->zoom)) {
 					AddStringToDraw(t->sign.left + 5, t->sign.top + 1, STR_TOWN_LABEL_TINY_BLACK, t->index, 0);
 					AddStringToDraw(t->sign.left + 1, t->sign.top - 3, STR_TOWN_LABEL_TINY_WHITE, t->index, 0);
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -882,7 +889,7 @@
 	bottom = top + dpi->height;
 
 	switch (dpi->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			FOR_ALL_STATIONS(st) {
 				if (bottom > st->sign.top &&
 						top    < st->sign.top + 12 &&
@@ -893,7 +900,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			right += 2;
 			bottom += 2;
 			FOR_ALL_STATIONS(st) {
@@ -906,19 +913,25 @@
 			}
 			break;
 
-		default: NOT_REACHED();
-		case 2:
-			right += 4;
-			bottom += 5;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			right += ScaleByZoom(1, dpi->zoom);
+			bottom += ScaleByZoom(1, dpi->zoom) + 1;
+
 			FOR_ALL_STATIONS(st) {
 				if (bottom > st->sign.top &&
-						top    < st->sign.top + 24 &&
+						top    < st->sign.top + ScaleByZoom(12, dpi->zoom) &&
 						right  > st->sign.left &&
-						left   < st->sign.left + st->sign.width_2*4) {
+						left   < st->sign.left + ScaleByZoom(st->sign.width_2, dpi->zoom)) {
 					AddStation(st, STR_STATION_SIGN_TINY, st->sign.width_2 | 0x8000);
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -949,7 +962,7 @@
 	bottom = top + dpi->height;
 
 	switch (dpi->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			FOR_ALL_SIGNS(si) {
 				if (bottom > si->sign.top &&
 						top    < si->sign.top + 12 &&
@@ -960,7 +973,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			right += 2;
 			bottom += 2;
 			FOR_ALL_SIGNS(si) {
@@ -973,19 +986,25 @@
 			}
 			break;
 
-		default: NOT_REACHED();
-		case 2:
-			right += 4;
-			bottom += 5;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			right += ScaleByZoom(1, dpi->zoom);
+			bottom += ScaleByZoom(1, dpi->zoom) + 1;
+
 			FOR_ALL_SIGNS(si) {
 				if (bottom > si->sign.top &&
-						top    < si->sign.top + 24 &&
+						top    < si->sign.top + ScaleByZoom(12, dpi->zoom) &&
 						right  > si->sign.left &&
-						left   < si->sign.left + si->sign.width_2 * 4) {
+						left   < si->sign.left + ScaleByZoom(si->sign.width_2, dpi->zoom)) {
 					AddSign(si, STR_2002, si->sign.width_2 | 0x8000);
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -1016,7 +1035,7 @@
 	bottom = top + dpi->height;
 
 	switch (dpi->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			FOR_ALL_WAYPOINTS(wp) {
 				if (bottom > wp->sign.top &&
 						top    < wp->sign.top + 12 &&
@@ -1027,7 +1046,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			right += 2;
 			bottom += 2;
 			FOR_ALL_WAYPOINTS(wp) {
@@ -1040,19 +1059,25 @@
 			}
 			break;
 
-		default: NOT_REACHED();
-		case 2:
-			right += 4;
-			bottom += 5;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			right += ScaleByZoom(1, dpi->zoom);
+			bottom += ScaleByZoom(1, dpi->zoom) + 1;
+
 			FOR_ALL_WAYPOINTS(wp) {
 				if (bottom > wp->sign.top &&
-						top    < wp->sign.top + 24 &&
+						top    < wp->sign.top + ScaleByZoom(12, dpi->zoom) &&
 						right  > wp->sign.left &&
-						left   < wp->sign.left + wp->sign.width_2*4) {
+						left   < wp->sign.left + ScaleByZoom(wp->sign.width_2, dpi->zoom)) {
 					AddWaypoint(wp, STR_WAYPOINT_VIEWPORT_TINY, wp->sign.width_2 | 0x8000);
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 }
 
@@ -1163,25 +1188,25 @@
 static void ViewportDrawStrings(DrawPixelInfo *dpi, const StringSpriteToDraw *ss)
 {
 	DrawPixelInfo dp;
-	byte zoom;
+	ZoomLevel zoom;
 
 	_cur_dpi = &dp;
 	dp = *dpi;
 
 	zoom = dp.zoom;
-	dp.zoom = 0;
-
-	dp.left >>= zoom;
-	dp.top >>= zoom;
-	dp.width >>= zoom;
-	dp.height >>= zoom;
+	dp.zoom = ZOOM_LVL_NORMAL;
+
+	dp.left   = UnScaleByZoom(dp.left,   zoom);
+	dp.top    = UnScaleByZoom(dp.top,    zoom);
+	dp.width  = UnScaleByZoom(dp.width,  zoom);
+	dp.height = UnScaleByZoom(dp.height, zoom);
 
 	do {
 		uint16 colour;
 
 		if (ss->width != 0) {
-			int x = (ss->x >> zoom) - 1;
-			int y = (ss->y >> zoom) - 1;
+			int x = UnScaleByZoom(ss->x, zoom) - 1;
+			int y = UnScaleByZoom(ss->y, zoom) - 1;
 			int bottom = y + 11;
 			int w = ss->width;
 
@@ -1214,7 +1239,7 @@
 			colour = 16;
 		}
 		DrawString(
-			ss->x >> zoom, (ss->y >> zoom) - (ss->width & 0x8000 ? 2 : 0),
+			UnScaleByZoom(ss->x, zoom), UnScaleByZoom(ss->y, zoom) - (ss->width & 0x8000 ? 2 : 0),
 			ss->string, colour
 		);
 
@@ -1239,7 +1264,7 @@
 	_cur_dpi = &vd.dpi;
 
 	vd.dpi.zoom = vp->zoom;
-	mask = (-1) << vp->zoom;
+	mask = ScaleByZoom(-1, vp->zoom);
 
 	vd.combine_sprites = 0;
 
@@ -1249,8 +1274,8 @@
 	vd.dpi.top = top & mask;
 	vd.dpi.pitch = old_dpi->pitch;
 
-	x = ((vd.dpi.left - (vp->virtual_left&mask)) >> vp->zoom) + vp->left;
-	y = ((vd.dpi.top - (vp->virtual_top&mask)) >> vp->zoom) + vp->top;
+	x = UnScaleByZoom(vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
+	y = UnScaleByZoom(vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
 
 	vd.dpi.dst_ptr = old_dpi->dst_ptr + x - old_dpi->left + (y - old_dpi->top) * old_dpi->pitch;
 
@@ -1293,7 +1318,7 @@
  * If we do, the sprite memory will overflow. */
 static void ViewportDrawChk(const ViewPort *vp, int left, int top, int right, int bottom)
 {
-	if (((bottom - top) * (right - left) << (2 * vp->zoom)) > 180000) {
+	if (ScaleByZoom(bottom - top, vp->zoom) * ScaleByZoom(right - left, vp->zoom) > 180000) {
 		if ((bottom - top) > (right - left)) {
 			int t = (top + bottom) >> 1;
 			ViewportDrawChk(vp, left, top, right, t);
@@ -1305,10 +1330,10 @@
 		}
 	} else {
 		ViewportDoDraw(vp,
-			((left - vp->left) << vp->zoom) + vp->virtual_left,
-			((top - vp->top) << vp->zoom) + vp->virtual_top,
-			((right - vp->left) << vp->zoom) + vp->virtual_left,
-			((bottom - vp->top) << vp->zoom) + vp->virtual_top
+			ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left,
+			ScaleByZoom(top - vp->top, vp->zoom) + vp->virtual_top,
+			ScaleByZoom(right - vp->left, vp->zoom) + vp->virtual_left,
+			ScaleByZoom(bottom - vp->top, vp->zoom) + vp->virtual_top
 		);
 	}
 }
@@ -1396,10 +1421,10 @@
 	if (top >= vp->virtual_height) return;
 
 	SetDirtyBlocks(
-		(left >> vp->zoom) + vp->left,
-		(top >> vp->zoom) + vp->top,
-		(right >> vp->zoom) + vp->left,
-		(bottom >> vp->zoom) + vp->top
+		UnScaleByZoom(left, vp->zoom) + vp->left,
+		UnScaleByZoom(top, vp->zoom) + vp->top,
+		UnScaleByZoom(right, vp->zoom) + vp->left,
+		UnScaleByZoom(bottom, vp->zoom) + vp->top
 	);
 }
 
@@ -1490,7 +1515,7 @@
 	if (!HASBIT(_display_opt, DO_SHOW_TOWN_NAMES)) return false;
 
 	switch (vp->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			x = x - vp->left + vp->virtual_left;
 			y = y - vp->top  + vp->virtual_top;
 			FOR_ALL_TOWNS(t) {
@@ -1504,7 +1529,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			x = (x - vp->left + 1) * 2 + vp->virtual_left;
 			y = (y - vp->top  + 1) * 2 + vp->virtual_top;
 			FOR_ALL_TOWNS(t) {
@@ -1518,19 +1543,26 @@
 			}
 			break;
 
-		default:
-			x = (x - vp->left + 3) * 4 + vp->virtual_left;
-			y = (y - vp->top  + 3) * 4 + vp->virtual_top;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			x = ScaleByZoom(x - vp->left + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_left;
+			y = ScaleByZoom(y - vp->top  + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_top;
+
 			FOR_ALL_TOWNS(t) {
 				if (y >= t->sign.top &&
-						y < t->sign.top + 24 &&
+						y < t->sign.top + ScaleByZoom(12, vp->zoom) &&
 						x >= t->sign.left &&
-						x < t->sign.left + t->sign.width_2 * 4) {
+						x < t->sign.left + ScaleByZoom(t->sign.width_2, vp->zoom)) {
 					ShowTownViewWindow(t->index);
 					return true;
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 
 	return false;
@@ -1544,7 +1576,7 @@
 	if (!HASBIT(_display_opt, DO_SHOW_STATION_NAMES)) return false;
 
 	switch (vp->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			x = x - vp->left + vp->virtual_left;
 			y = y - vp->top  + vp->virtual_top;
 			FOR_ALL_STATIONS(st) {
@@ -1558,7 +1590,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			x = (x - vp->left + 1) * 2 + vp->virtual_left;
 			y = (y - vp->top  + 1) * 2 + vp->virtual_top;
 			FOR_ALL_STATIONS(st) {
@@ -1572,19 +1604,26 @@
 			}
 			break;
 
-		default:
-			x = (x - vp->left + 3) * 4 + vp->virtual_left;
-			y = (y - vp->top  + 3) * 4 + vp->virtual_top;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			x = ScaleByZoom(x - vp->left + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_left;
+			y = ScaleByZoom(y - vp->top  + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_top;
+
 			FOR_ALL_STATIONS(st) {
 				if (y >= st->sign.top &&
-						y < st->sign.top + 24 &&
+						y < st->sign.top + ScaleByZoom(12, vp->zoom) &&
 						x >= st->sign.left &&
-						x < st->sign.left + st->sign.width_2 * 4) {
+						x < st->sign.left + ScaleByZoom(st->sign.width_2, vp->zoom)) {
 					ShowStationViewWindow(st->index);
 					return true;
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 
 	return false;
@@ -1598,7 +1637,7 @@
 	if (!HASBIT(_display_opt, DO_SHOW_SIGNS) || _current_player == PLAYER_SPECTATOR) return false;
 
 	switch (vp->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			x = x - vp->left + vp->virtual_left;
 			y = y - vp->top  + vp->virtual_top;
 			FOR_ALL_SIGNS(si) {
@@ -1612,7 +1651,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			x = (x - vp->left + 1) * 2 + vp->virtual_left;
 			y = (y - vp->top  + 1) * 2 + vp->virtual_top;
 			FOR_ALL_SIGNS(si) {
@@ -1626,19 +1665,26 @@
 			}
 			break;
 
-		default:
-			x = (x - vp->left + 3) * 4 + vp->virtual_left;
-			y = (y - vp->top  + 3) * 4 + vp->virtual_top;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			x = ScaleByZoom(x - vp->left + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_left;
+			y = ScaleByZoom(y - vp->top  + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_top;
+
 			FOR_ALL_SIGNS(si) {
 				if (y >= si->sign.top &&
-						y <  si->sign.top + 24 &&
+						y <  si->sign.top + ScaleByZoom(12, vp->zoom) &&
 						x >= si->sign.left &&
-						x <  si->sign.left + si->sign.width_2 * 4) {
+						x <  si->sign.left + ScaleByZoom(si->sign.width_2, vp->zoom)) {
 					ShowRenameSignWindow(si);
 					return true;
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 
 	return false;
@@ -1652,7 +1698,7 @@
 	if (!HASBIT(_display_opt, DO_WAYPOINTS)) return false;
 
 	switch (vp->zoom) {
-		case 0:
+		case ZOOM_LVL_NORMAL:
 			x = x - vp->left + vp->virtual_left;
 			y = y - vp->top  + vp->virtual_top;
 			FOR_ALL_WAYPOINTS(wp) {
@@ -1666,7 +1712,7 @@
 			}
 			break;
 
-		case 1:
+		case ZOOM_LVL_OUT_2X:
 			x = (x - vp->left + 1) * 2 + vp->virtual_left;
 			y = (y - vp->top  + 1) * 2 + vp->virtual_top;
 			FOR_ALL_WAYPOINTS(wp) {
@@ -1680,19 +1726,26 @@
 			}
 			break;
 
-		default:
-			x = (x - vp->left + 3) * 4 + vp->virtual_left;
-			y = (y - vp->top  + 3) * 4 + vp->virtual_top;
+		case ZOOM_LVL_OUT_4X:
+		case ZOOM_LVL_OUT_8X:
+			x = ScaleByZoom(x - vp->left + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_left;
+			y = ScaleByZoom(y - vp->top  + ScaleByZoom(1, vp->zoom) - 1, vp->zoom) + vp->virtual_top;
+
 			FOR_ALL_WAYPOINTS(wp) {
 				if (y >= wp->sign.top &&
-						y < wp->sign.top + 24 &&
+						y < wp->sign.top + ScaleByZoom(12, vp->zoom) &&
 						x >= wp->sign.left &&
-						x < wp->sign.left + wp->sign.width_2 * 4) {
+						x < wp->sign.left + ScaleByZoom(wp->sign.width_2, vp->zoom)) {
 					ShowRenameWaypointWindow(wp);
 					return true;
 				}
 			}
 			break;
+
+		case ZOOM_LVL_OUT_16X:
+			break;
+
+		default: NOT_REACHED();
 	}
 
 	return false;
@@ -1932,9 +1985,10 @@
 }
 
 /** highlighting tiles while only going over them with the mouse */
-void VpStartPlaceSizing(TileIndex tile, int user)
+void VpStartPlaceSizing(TileIndex tile, byte method, byte process)
 {
-	_thd.userdata = user;
+	_thd.select_method = method;
+	_thd.select_proc   = process;
 	_thd.selend.x = TileX(tile) * TILE_SIZE;
 	_thd.selstart.x = TileX(tile) * TILE_SIZE;
 	_thd.selend.y = TileY(tile) * TILE_SIZE;
@@ -2392,7 +2446,8 @@
 
 	if (_special_mouse_mode != WSM_SIZING) return true;
 
-	e.we.place.userdata = _thd.userdata;
+	e.we.place.select_method = _thd.select_method;
+	e.we.place.select_proc   = _thd.select_proc;
 
 	/* stop drag mode if the window has been closed */
 	w = FindWindowById(_thd.window_class, _thd.window_number);
@@ -2414,7 +2469,7 @@
 	_special_mouse_mode = WSM_NONE;
 	if (_thd.next_drawstyle == HT_RECT) {
 		_thd.place_mode = VHM_RECT;
-	} else if ((e.we.place.userdata & 0xF) == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
+	} else if (e.we.place.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
 		_thd.place_mode = VHM_RECT;
 	} else if (_thd.next_drawstyle & HT_LINE) {
 		_thd.place_mode = VHM_RAIL;
--- a/src/viewport.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/viewport.h	Fri May 25 00:25:08 2007 +0000
@@ -5,6 +5,8 @@
 #ifndef VIEWPORT_H
 #define VIEWPORT_H
 
+#include "zoom.hpp"
+
 struct ViewPort {
 	int left,top;                       // screen coordinates for the viewport
 	int width, height;                  // screen width/height for the viewport
@@ -12,7 +14,7 @@
 	int virtual_left, virtual_top;      // virtual coordinates
 	int virtual_width, virtual_height;  // these are just width << zoom, height << zoom
 
-	byte zoom;
+	ZoomLevel zoom;
 };
 
 void SetSelectionRed(bool);
@@ -21,7 +23,7 @@
 void InitViewports();
 void DeleteWindowViewport(Window *w);
 void AssignWindowViewport(Window *w, int x, int y,
-	int width, int height, uint32 follow_flags, byte zoom);
+	int width, int height, uint32 follow_flags, ZoomLevel zoom);
 ViewPort *IsPtInWindowViewport(const Window *w, int x, int y);
 Point GetTileBelowCursor();
 void UpdateViewportPosition(Window *w);
@@ -60,7 +62,7 @@
 void SetTileSelectSize(int w, int h);
 void SetTileSelectBigSize(int ox, int oy, int sx, int sy);
 
-void VpStartPlaceSizing(TileIndex tile, int user);
+void VpStartPlaceSizing(TileIndex tile, byte method, byte process);
 void VpSetPresizeRange(uint from, uint to);
 void VpSetPlaceSizingLimit(int limit);
 
@@ -135,7 +137,9 @@
 	WindowClass window_class;
 	WindowNumber window_number;
 
-	int userdata;
+	byte select_method;
+	byte select_proc;
+
 	TileIndex redsq;
 };
 
--- a/src/water_cmd.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/water_cmd.cpp	Fri May 25 00:25:08 2007 +0000
@@ -725,7 +725,7 @@
 	}
 }
 
-static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	static const byte coast_tracks[] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0};
 
--- a/src/win32.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/win32.cpp	Fri May 25 00:25:08 2007 +0000
@@ -890,6 +890,9 @@
 #endif /* UNICODE */
 
 #if defined(UNICODE)
+	/* Check if a win9x user started the win32 version */
+	if (HASBIT(GetVersion(), 31)) error("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again.");
+
 	/* For UNICODE we need to convert the commandline to char* _AND_
 	 * save it because argv[] points into this buffer and thus needs to
 	 * be available between subsequent calls to FS2OTTD() */
--- a/src/window.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/window.cpp	Fri May 25 00:25:08 2007 +0000
@@ -271,7 +271,7 @@
 		dp->top = top - (*wz)->top;
 		dp->pitch = _screen.pitch;
 		dp->dst_ptr = _screen.dst_ptr + top * _screen.pitch + left;
-		dp->zoom = 0;
+		dp->zoom = ZOOM_LVL_NORMAL;
 		CallWindowEventNP(*wz, WE_PAINT);
 	}
 }
@@ -1618,14 +1618,14 @@
 			/* here allows scrolling in both x and y axis */
 #define scrollspeed 3
 			if (x - 15 < 0) {
-				WP(w, vp_d).scrollpos_x += (x - 15) * scrollspeed << vp->zoom;
+				WP(w, vp_d).scrollpos_x += ScaleByZoom((x - 15) * scrollspeed, vp->zoom);
 			} else if (15 - (vp->width - x) > 0) {
-				WP(w, vp_d).scrollpos_x += (15 - (vp->width - x)) * scrollspeed << vp->zoom;
+				WP(w, vp_d).scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * scrollspeed, vp->zoom);
 			}
 			if (y - 15 < 0) {
-				WP(w, vp_d).scrollpos_y += (y - 15) * scrollspeed << vp->zoom;
+				WP(w, vp_d).scrollpos_y += ScaleByZoom((y - 15) * scrollspeed, vp->zoom);
 			} else if (15 - (vp->height - y) > 0) {
-				WP(w,vp_d).scrollpos_y += (15 - (vp->height - y)) * scrollspeed << vp->zoom;
+				WP(w,vp_d).scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * scrollspeed, vp->zoom);
 			}
 #undef scrollspeed
 		}
@@ -1970,8 +1970,8 @@
 			ViewPort *vp = w->viewport;
 			vp->width = w->width = neww;
 			vp->height = w->height = newh;
-			vp->virtual_width = neww << vp->zoom;
-			vp->virtual_height = newh << vp->zoom;
+			vp->virtual_width = ScaleByZoom(neww, vp->zoom);
+			vp->virtual_height = ScaleByZoom(newh, vp->zoom);
 			continue; // don't modify top,left
 		}
 
--- a/src/window.h	Fri May 11 15:13:08 2007 +0000
+++ b/src/window.h	Fri May 25 00:25:08 2007 +0000
@@ -9,7 +9,9 @@
 #include "string.h"
 #include "order.h"
 #include "rail.h"
+#include "road.h"
 #include "airport.h"
+#include "vehicle.h"
 
 struct WindowEvent;
 
@@ -133,7 +135,8 @@
 			Point pt;
 			TileIndex tile;
 			TileIndex starttile;
-			int userdata;
+			byte select_method;
+			byte select_proc;
 		} place;
 
 		struct {
@@ -323,10 +326,11 @@
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tooltips_d));
 
 struct buildvehicle_d {
-	byte vehicle_type;
+	VehicleType vehicle_type;
 	union {
 		RailTypeByte railtype;
 		AirportFTAClass::Flags flags;
+		RoadTypes roadtypes;
 	} filter;
 	byte sel_index;  ///< deprecated value, used for 'unified' ship and road
 	bool descending_sort_order;
@@ -347,12 +351,13 @@
 	bool update_left;
 	bool update_right;
 	bool init_lists;
+	GroupID sel_group;
 };
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d));
 
 struct depot_d {
 	VehicleID sel;
-	byte type;
+	VehicleType type;
 	bool generate_list;
 	uint16 engine_list_length;
 	uint16 wagon_list_length;
@@ -477,6 +482,28 @@
 };
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(dropdown_d));
 
+struct vehiclelist_d {
+	const Vehicle** sort_list;  // List of vehicles (sorted)
+	Listing *_sorting;          // pointer to the appropiate subcategory of _sorting
+	uint16 length_of_sort_list; // Keeps track of how many vehicle pointers sort list got space for
+	VehicleType vehicle_type;   // The vehicle type that is sorted
+	list_d l;                   // General list struct
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d));
+
+struct grouplist_d {
+	const Group **sort_list;
+	list_d l;                   // General list struct
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(grouplist_d));
+
+struct groupveh_d : vehiclelist_d {
+	GroupID group_sel;
+	VehicleID vehicle_sel;
+
+	grouplist_d gl;
+};
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(groupveh_d));
 
 /****************** THESE ARE NOT WIDGET TYPES!!!!! *******************/
 enum WindowWidgetBehaviours {
--- a/src/yapf/follow_track.hpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/yapf/follow_track.hpp	Fri May 25 00:25:08 2007 +0000
@@ -45,7 +45,7 @@
 	{
 		m_old_tile = old_tile;
 		m_old_td = old_td;
-		assert((GetTileTrackStatus(m_old_tile, TT()) & TrackdirToTrackdirBits(m_old_td)) != 0);
+		assert((GetTileTrackStatus(m_old_tile, TT(), m_veh->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(m_old_td)) != 0);
 		m_exitdir = TrackdirToExitdir(m_old_td);
 		if (EnteredDepot()) return true;
 		if (!CanExitOldTile()) return false;
@@ -114,7 +114,7 @@
 		if (IsRailTT() && GetTileType(m_new_tile) == MP_RAILWAY && IsPlainRailTile(m_new_tile)) {
 			m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
 		} else {
-			uint32 ts = GetTileTrackStatus(m_new_tile, TT());
+			uint32 ts = GetTileTrackStatus(m_new_tile, TT(), m_veh->u.road.compatible_roadtypes);
 			m_new_td_bits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
 		}
 		return (m_new_td_bits != TRACKDIR_BIT_NONE);
--- a/src/yapf/yapf.hpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/yapf/yapf.hpp	Fri May 25 00:25:08 2007 +0000
@@ -7,6 +7,7 @@
 
 #include "track_dir.hpp"
 
+#include "../vehicle.h"
 #include "../depot.h"
 #include "../road_map.h"
 #include "../tunnel_map.h"
@@ -14,7 +15,6 @@
 #include "../bridge.h"
 #include "../station.h"
 #include "../station_map.h"
-#include "../vehicle.h"
 #include "../date.h"
 #include "../functions.h"
 #include "../landscape.h"
--- a/src/yapf/yapf_destrail.hpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/yapf/yapf_destrail.hpp	Fri May 25 00:25:08 2007 +0000
@@ -113,7 +113,7 @@
 			default:
 				m_destTile = v->dest_tile;
 				m_dest_station_id = INVALID_STATION;
-				m_destTrackdirs = (TrackdirBits)(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL) & TRACKDIR_BIT_MASK);
+				m_destTrackdirs = (TrackdirBits)(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0) & TRACKDIR_BIT_MASK);
 				break;
 		}
 		CYapfDestinationRailBase::SetDestination(v);
--- a/src/yapf/yapf_road.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/yapf/yapf_road.cpp	Fri May 25 00:25:08 2007 +0000
@@ -268,14 +268,14 @@
 		// our source tile will be the next vehicle tile (should be the given one)
 		TileIndex src_tile = tile;
 		// get available trackdirs on the start tile
-		uint ts = GetTileTrackStatus(tile, TRANSPORT_ROAD);
+		uint ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
 		TrackdirBits src_trackdirs = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
 		// select reachable trackdirs only
 		src_trackdirs &= DiagdirReachesTrackdirs(enterdir);
 
 		// get available trackdirs on the destination tile
 		TileIndex dest_tile = v->dest_tile;
-		uint dest_ts = GetTileTrackStatus(dest_tile, TRANSPORT_ROAD);
+		uint dest_ts = GetTileTrackStatus(dest_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
 		TrackdirBits dest_trackdirs = (TrackdirBits)(dest_ts & TRACKDIR_BIT_MASK);
 
 		// set origin and destination nodes
@@ -320,7 +320,7 @@
 
 		// set destination tile, trackdir
 		//   get available trackdirs on the destination tile
-		uint dest_ts = GetTileTrackStatus(dst_tile, TRANSPORT_ROAD);
+		uint dest_ts = GetTileTrackStatus(dst_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes);
 		TrackdirBits dst_td_bits = (TrackdirBits)(dest_ts & TRACKDIR_BIT_MASK);
 		Yapf().SetDestination(dst_tile, dst_td_bits);
 
@@ -345,7 +345,7 @@
 		// set origin (tile, trackdir)
 		TileIndex src_tile = v->tile;
 		Trackdir src_td = GetVehicleTrackdir(v);
-		if ((GetTileTrackStatus(src_tile, TRANSPORT_ROAD) & TrackdirToTrackdirBits(src_td)) == 0) {
+		if ((GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(src_td)) == 0) {
 			// sometimes the roadveh is not on the road (it resides on non-existing track)
 			// how should we handle that situation?
 			return false;
@@ -438,7 +438,7 @@
 {
 	TileIndex tile = v->tile;
 	Trackdir trackdir = GetVehicleTrackdir(v);
-	if ((GetTileTrackStatus(tile, TRANSPORT_ROAD) & TrackdirToTrackdirBits(trackdir)) == 0)
+	if ((GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes) & TrackdirToTrackdirBits(trackdir)) == 0)
 		return NULL;
 
 	// handle the case when our vehicle is already in the depot tile
--- a/src/yapf/yapf_ship.cpp	Fri May 11 15:13:08 2007 +0000
+++ b/src/yapf/yapf_ship.cpp	Fri May 25 00:25:08 2007 +0000
@@ -53,7 +53,7 @@
 		// convert origin trackdir to TrackdirBits
 		TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
 		// get available trackdirs on the destination tile
-		TrackdirBits dest_trackdirs = (TrackdirBits)(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER) & TRACKDIR_BIT_MASK);
+		TrackdirBits dest_trackdirs = (TrackdirBits)(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0) & TRACKDIR_BIT_MASK);
 
 		// create pathfinder instance
 		Tpf pf;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/zoom.hpp	Fri May 25 00:25:08 2007 +0000
@@ -0,0 +1,50 @@
+/* $Id$ */
+
+/** @file zoom.hpp */
+
+#ifndef ZOOM_HPP
+#define ZOOM_HPP
+
+enum ZoomLevel {
+	/* Our possible zoom-levels */
+	ZOOM_LVL_NORMAL = 0,
+	ZOOM_LVL_OUT_2X,
+	ZOOM_LVL_OUT_4X,
+	ZOOM_LVL_OUT_8X,
+	ZOOM_LVL_OUT_16X,
+	ZOOM_LVL_END,
+
+	/* Here we define in which zoom viewports are */
+	ZOOM_LVL_VIEWPORT = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_NEWS     = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_INDUSTRY = ZOOM_LVL_OUT_2X,
+	ZOOM_LVL_TOWN     = ZOOM_LVL_OUT_2X,
+	ZOOM_LVL_AIRCRAFT = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_SHIP     = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_TRAIN    = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_ROADVEH  = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_WORLD_SCREENSHOT = ZOOM_LVL_NORMAL,
+
+	ZOOM_LVL_DETAIL   = ZOOM_LVL_OUT_2X, //! All zoomlevels below or equal to this, will result in details on the screen, like road-work, ...
+
+	ZOOM_LVL_MIN      = ZOOM_LVL_NORMAL,
+	ZOOM_LVL_MAX      = ZOOM_LVL_OUT_16X,
+};
+
+extern ZoomLevel _saved_scrollpos_zoom;
+
+static inline int ScaleByZoom(int value, ZoomLevel zoom)
+{
+	if (zoom == ZOOM_LVL_NORMAL) return value;
+	int izoom = (int)zoom - (int)ZOOM_LVL_NORMAL;
+	return (zoom > ZOOM_LVL_NORMAL) ? value << izoom : value >> izoom;
+}
+
+static inline int UnScaleByZoom(int value, ZoomLevel zoom)
+{
+	if (zoom == ZOOM_LVL_NORMAL) return value;
+	int izoom = (int)zoom - (int)ZOOM_LVL_NORMAL;
+	return (zoom > ZOOM_LVL_NORMAL) ? value >> izoom : value << izoom;
+}
+
+#endif /* ZOOM_HPP */