# smallmap_gui.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "clear_map.h"
    00014 #include "industry.h"
    00015 #include "station_map.h"
    00016 #include "landscape.h"
    00017 #include "window_gui.h"
    00018 #include "tree_map.h"
    00019 #include "viewport_func.h"
    00020 #include "town.h"
    00021 #include "blitter/factory.hpp"
    00022 #include "tunnelbridge_map.h"
    00023 #include "strings_func.h"
    00024 #include "core/endian_func.hpp"
    00025 #include "vehicle_base.h"
    00026 #include "sound_func.h"
    00027 #include "window_func.h"
    00028 #include "company_base.h"
    00029 //#include "cargotype.h"
    00030 //#include "openttd.h"
    00031 #include "company_func.h"
    00032 #include "station_base.h"
    00033
    00034 #include "table/strings.h"
    00035
    00036 //#include <cmath>
    00037 #include <vector>
    00038
    00040 enum SmallMapWindowWidgets {
    00041   SM_WIDGET_CAPTION,
    00042   SM_WIDGET_MAP_BORDER,
    00043   SM_WIDGET_MAP,
    00044   SM_WIDGET_LEGEND,
    00045   SM_WIDGET_BLANK,
    00046   SM_WIDGET_ZOOM_IN,
    00047   SM_WIDGET_ZOOM_OUT,
    00048   SM_WIDGET_CONTOUR,
    00049   SM_WIDGET_VEHICLES,
    00050   SM_WIDGET_INDUSTRIES,
    00051   SM_WIDGET_LINKSTATS,
    00052   SM_WIDGET_ROUTES,
    00053   SM_WIDGET_VEGETATION,
    00054   SM_WIDGET_OWNERS,
    00055   SM_WIDGET_CENTERMAP,
    00056   SM_WIDGET_TOGGLETOWNNAME,
    00057   SM_WIDGET_SELECT_BUTTONS,
    00058   SM_WIDGET_ENABLE_ALL,
    00059   SM_WIDGET_DISABLE_ALL,
    00060   SM_WIDGET_SHOW_HEIGHT,
    00061 };
    00062
    00063 static int _smallmap_industry_count;
    00064 static int _smallmap_company_count;
    00065 static const int NUM_NO_COMPANY_ENTRIES = 4;
    00066 static int _smallmap_cargo_count;
    00067
    00068 static const uint8 PC_ROUGH_LAND      = 0x52;
    00069 static const uint8 PC_GRASS_LAND      = 0x54;
    00070 static const uint8 PC_BARE_LAND       = 0x37;
    00071 static const uint8 PC_FIELDS          = 0x25;
    00072 static const uint8 PC_TREES           = 0x57;
    00073 static const uint8 PC_WATER           = 0xCA;
    00074
    00075 enum SmallMapStats {
    00076   STAT_CAPACITY,
    00077   STAT_BEGIN = STAT_CAPACITY,
    00078   STAT_USAGE,
    00079   STAT_PLANNED,
    00080   STAT_SENT,
    00081   STAT_TEXT,
    00082   STAT_GRAPH,
    00083   STAT_END,
    00084   NUM_STATS = STAT_END,
    00085 };
    00086
    00088 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
    00089
    00091 #define MC(height)  {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, false}
    00092
    00097 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
    00098
    00100 #define MCS(height)  {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, true}
    00101
    00103 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
    00104
    00106 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
    00107
    00109 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
    00110
    00112 struct LegendAndColour {
    00113   uint8 colour;
    00114   StringID legend;
    00115   IndustryType type;
    00116   uint8 height;
    00117   CompanyID company;
    00118   bool show_on_map;
    00119   bool end;
    00120   bool col_break;
    00121 };
    00122
    00124 static LegendAndColour _legend_land_contours_old[] = {
    00125   /* The colours for the following values are set at BuildLandLegend() based on each colour scheme when the more height levels patch is off. */
    00126   MC(1),
    00127   MC(5),
    00128   MC(9),
    00129   MC(13),
    00130   MC(15),
    00131
    00132   MS(PC_BLACK,           STR_SMALLMAP_LEGENDA_ROADS),
    00133   MK(PC_GREY,            STR_SMALLMAP_LEGENDA_RAILROADS),
    00134   MK(PC_LIGHT_BLUE,      STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
    00135   MK(PC_DARK_RED,        STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
    00136   MK(PC_WHITE,           STR_SMALLMAP_LEGENDA_VEHICLES),
    00137   MKEND()
    00138 };
    00139
    00141 static LegendAndColour _legend_land_contours_extended[] = {
    00142   /* The colours for the following values are set at BuildLandLegend() based on each colour scheme when the more height levels patch is on. */
    00143   MC(1),
    00144   MC(16),
    00145   MC(32),
    00146   MC(48),
    00147   MC(64),
    00148   MC(80),
    00149
    00150   MCS(96),
    00151   MC(112),
    00152   MC(128),
    00153   MC(144),
    00154   MC(160),
    00155   MC(176),
    00156
    00157   MCS(192),
    00158   MC(208),
    00159   MC(224),
    00160   MC(240),
    00161   MC(255),
    00162
    00163   MS(PC_BLACK,      STR_SMALLMAP_LEGENDA_ROADS),
    00164   MK(PC_GREY,       STR_SMALLMAP_LEGENDA_RAILROADS),
    00165   MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
    00166   MK(PC_DARK_RED,   STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
    00167   MK(PC_WHITE,      STR_SMALLMAP_LEGENDA_VEHICLES),
    00168   MKEND()
    00169 };
    00170
    00171 static const LegendAndColour _legend_vehicles[] = {
    00172   MK(PC_RED,             STR_SMALLMAP_LEGENDA_TRAINS),
    00173   MK(PC_YELLOW,          STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
    00174   MK(PC_LIGHT_BLUE,      STR_SMALLMAP_LEGENDA_SHIPS),
    00175   MK(PC_WHITE,           STR_SMALLMAP_LEGENDA_AIRCRAFT),
    00176
    00177   MS(PC_BLACK,           STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
    00178   MK(PC_DARK_RED,        STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
    00179   MKEND()
    00180 };
    00181
    00182 static const LegendAndColour _legend_routes[] = {
    00183   MK(PC_BLACK,           STR_SMALLMAP_LEGENDA_ROADS),
    00184   MK(PC_GREY,            STR_SMALLMAP_LEGENDA_RAILROADS),
    00185   MK(PC_DARK_RED,        STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
    00186
    00187   MS(PC_VERY_DARK_BROWN, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
    00188   MK(PC_ORANGE,          STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
    00189   MK(PC_YELLOW,          STR_SMALLMAP_LEGENDA_BUS_STATION),
    00190   MK(PC_RED,             STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
    00191   MK(PC_LIGHT_BLUE,      STR_SMALLMAP_LEGENDA_DOCK),
    00192   MKEND()
    00193 };
    00194
    00195 static const LegendAndColour _legend_vegetation[] = {
    00196   MK(PC_ROUGH_LAND,      STR_SMALLMAP_LEGENDA_ROUGH_LAND),
    00197   MK(PC_GRASS_LAND,      STR_SMALLMAP_LEGENDA_GRASS_LAND),
    00198   MK(PC_BARE_LAND,       STR_SMALLMAP_LEGENDA_BARE_LAND),
    00199   MK(PC_FIELDS,          STR_SMALLMAP_LEGENDA_FIELDS),
    00200   MK(PC_TREES,           STR_SMALLMAP_LEGENDA_TREES),
    00201   MK(PC_GREEN,           STR_SMALLMAP_LEGENDA_FOREST),
    00202
    00203   MS(PC_GREY,            STR_SMALLMAP_LEGENDA_ROCKS),
    00204   MK(PC_ORANGE,          STR_SMALLMAP_LEGENDA_DESERT),
    00205   MK(PC_LIGHT_BLUE,      STR_SMALLMAP_LEGENDA_SNOW),
    00206   MK(PC_BLACK,           STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
    00207   MK(PC_DARK_RED,        STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
    00208   MKEND()
    00209 };
    00210
    00211 static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
    00212   MO(PC_WATER,           STR_SMALLMAP_LEGENDA_WATER),
    00213   MO(0x00,               STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings.
    00214   MO(PC_DARK_RED,        STR_SMALLMAP_LEGENDA_TOWNS),
    00215   MO(PC_DARK_GREY,       STR_SMALLMAP_LEGENDA_INDUSTRIES),
    00216   /* The legend will be terminated the first time it is used. */
    00217   MOEND(),
    00218 };
    00219
    00220 #undef MK
    00221 #undef MC
    00222 #undef MS
    00223 #undef MCS
    00224 #undef MO
    00225 #undef MOEND
    00226 #undef MKEND
    00227
    00232 static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES + 1];
    00234 static uint _industry_to_list_pos[NUM_INDUSTRYTYPES];
    00236 static bool _smallmap_show_heightmap = false;
    00238 static uint _company_to_list_pos[MAX_COMPANIES];
    00239
    00243 void BuildIndustriesLegend()
    00244 {
    00245   uint j = 0;
    00246
    00247   /* Add each name */
    00248   for (uint8 i = 0; i < NUM_INDUSTRYTYPES; i++) {
    00249     IndustryType ind = _sorted_industry_types[i];
    00250     const IndustrySpec *indsp = GetIndustrySpec(ind);
    00251     if (indsp->enabled) {
    00252       _legend_from_industries[j].legend = indsp->name;
    00253       _legend_from_industries[j].colour = indsp->map_colour;
    00254       _legend_from_industries[j].type = ind;
    00255       _legend_from_industries[j].show_on_map = true;
    00256       _legend_from_industries[j].col_break = false;
    00257       _legend_from_industries[j].end = false;
    00258
    00259       /* Store widget number for this industry type. */
    00260       _industry_to_list_pos[ind] = j;
    00261       j++;
    00262     }
    00263   }
    00264   /* Terminate the list */
    00265   _legend_from_industries[j].end = true;
    00266
    00267   /* Store number of enabled industries */
    00268   _smallmap_industry_count = j;
    00269 }
    00270
    00271 static LegendAndColour _legend_linkstats[NUM_CARGO + NUM_STATS + 1];
    00272
    00276 void BuildLinkStatsLegend()
    00277 {
    00278   /* Clear the legend */
    00279   memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
    00280
    00281   uint i = 0;
    00282   for (; i < _sorted_cargo_specs_size; ++i) {
    00283     const CargoSpec *cs = _sorted_cargo_specs[i];
    00284
    00285     _legend_linkstats[i].legend = cs->name;
    00286     _legend_linkstats[i].colour = cs->legend_colour;
    00287     _legend_linkstats[i].type = cs->Index();
    00288     _legend_linkstats[i].show_on_map = true;
    00289   }
    00290
    00291   _legend_linkstats[i].col_break = true;
    00292
    00293   _smallmap_cargo_count = i;
    00294
    00295   /* the colours cannot be resolved before the gfx system is initialized.
    00296    * So we have to build the legend when creating the window.
    00297    */
    00298   for (uint st = 0; st < NUM_STATS; ++st) {
    00299     LegendAndColour & legend_entry = _legend_linkstats[i + st];
    00300     switch(st) {
    00301     case STAT_CAPACITY:
    00302       legend_entry.colour = _colour_gradient[COLOUR_WHITE][7];
    00303       legend_entry.legend = STR_SMALLMAP_LEGENDA_CAPACITY;
    00304       legend_entry.show_on_map = true;
    00305       break;
    00306     case STAT_USAGE:
    00307       legend_entry.colour = _colour_gradient[COLOUR_GREY][1];
    00308       legend_entry.legend = STR_SMALLMAP_LEGENDA_USAGE;
    00309       legend_entry.show_on_map = false;
    00310       break;
    00311     case STAT_PLANNED:
    00312       legend_entry.colour = _colour_gradient[COLOUR_RED][5];
    00313       legend_entry.legend = STR_SMALLMAP_LEGENDA_PLANNED;
    00314       legend_entry.show_on_map = true;
    00315       break;
    00316     case STAT_SENT:
    00317       legend_entry.colour = _colour_gradient[COLOUR_YELLOW][5];
    00318       legend_entry.legend = STR_SMALLMAP_LEGENDA_SENT;
    00319       legend_entry.show_on_map = false;
    00320       break;
    00321     case STAT_TEXT:
    00322       legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
    00323       legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_TEXT;
    00324       legend_entry.show_on_map = false;
    00325       break;
    00326     case STAT_GRAPH:
    00327       legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
    00328       legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_GRAPH;
    00329       legend_entry.show_on_map = true;
    00330       break;
    00331     }
    00332   }
    00333
    00334   _legend_linkstats[i + NUM_STATS].end = true;
    00335 }
    00336
    00337 static const LegendAndColour * const _legend_table_old[] = {
    00338   _legend_land_contours_old,
    00339   _legend_vehicles,
    00340   _legend_from_industries,
    00341   _legend_linkstats,
    00342   _legend_routes,
    00343   _legend_vegetation,
    00344   _legend_land_owners,
    00345 };
    00346
    00347 static const LegendAndColour * const _legend_table_extended[] = {
    00348   _legend_land_contours_extended,
    00349   _legend_vehicles,
    00350   _legend_from_industries,
    00351   _legend_linkstats,
    00352   _legend_routes,
    00353   _legend_vegetation,
    00354   _legend_land_owners,
    00355 };
    00356
    00357 #define MKCOLOUR(x)         TO_LE32X(x)
    00358
    00359 #define MKCOLOUR_XXXX(x)    (MKCOLOUR(0x01010101) * (uint)(x))
    00360 #define MKCOLOUR_X0X0(x)    (MKCOLOUR(0x01000100) * (uint)(x))
    00361 #define MKCOLOUR_0X0X(x)    (MKCOLOUR(0x00010001) * (uint)(x))
    00362 #define MKCOLOUR_0XX0(x)    (MKCOLOUR(0x00010100) * (uint)(x))
    00363 #define MKCOLOUR_X00X(x)    (MKCOLOUR(0x01000001) * (uint)(x))
    00364
    00365 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
    00366 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
    00367
    00368 #define MKCOLOUR_0000       MKCOLOUR_XXXX(0x00)
    00369 #define MKCOLOUR_0FF0       MKCOLOUR_0XX0(0xFF)
    00370 #define MKCOLOUR_F00F       MKCOLOUR_X00X(0xFF)
    00371 #define MKCOLOUR_FFFF       MKCOLOUR_XXXX(0xFF)
    00372
    00377 static const uint32 _green_map_heights_old[] = {
    00378   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    00379   MKCOLOUR_XXXX(0x5A),
    00380   MKCOLOUR_XYXY(0x5A, 0x5B),
    00381   MKCOLOUR_XXXX(0x5B),
    00382   MKCOLOUR_XYXY(0x5B, 0x5C),
    00383   MKCOLOUR_XXXX(0x5C),
    00384   MKCOLOUR_XYXY(0x5C, 0x5D),
    00385   MKCOLOUR_XXXX(0x5D),
    00386   MKCOLOUR_XYXY(0x5D, 0x5E),
    00387   MKCOLOUR_XXXX(0x5E),
    00388   MKCOLOUR_XYXY(0x5E, 0x5F),
    00389   MKCOLOUR_XXXX(0x5F),
    00390   MKCOLOUR_XYXY(0x5F, 0x1F),
    00391   MKCOLOUR_XXXX(0x1F),
    00392   MKCOLOUR_XYXY(0x1F, 0x27),
    00393   MKCOLOUR_XXXX(0x27),
    00394   MKCOLOUR_XXXX(0x27),
    00395 };
    00396 assert_compile(lengthof(_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
    00397
    00403 static const uint32 _green_map_heights_extended[] = {
    00404   /* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
    00405   //MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
    00406   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    00407   MKCOLOUR(0x59595958), // height 1
    00408   MKCOLOUR(0x59595958), // height 2
    00409   MKCOLOUR(0X59595959), // height 3
    00410   MKCOLOUR(0X59595959), // height 4
    00411   MKCOLOUR(0X5959595A), // height 5
    00412   MKCOLOUR(0X5959595A), // height 6
    00413   MKCOLOUR(0X59595A59), // height 7
    00414   MKCOLOUR(0X59595A59), // height 8
    00415   MKCOLOUR(0X59595A5A), // height 9
    00416   MKCOLOUR(0X59595A5A), // height 10
    00417   MKCOLOUR(0X595A5959), // height 11
    00418   MKCOLOUR(0X595A5959), // height 12
    00419   MKCOLOUR(0X595A595A), // height 13
    00420   MKCOLOUR(0X595A595A), // height 14
    00421   MKCOLOUR(0X595A5A59), // height 15
    00422   MKCOLOUR(0X595A5A59), // height 16
    00423   MKCOLOUR(0X595A5A5A), // height 17
    00424   MKCOLOUR(0X595A5A5A), // height 18
    00425   MKCOLOUR(0X5A595959), // height 19
    00426   MKCOLOUR(0X5A595959), // height 20
    00427   MKCOLOUR(0X5A59595A), // height 21
    00428   MKCOLOUR(0X5A59595A), // height 22
    00429   MKCOLOUR(0X5A595A59), // height 23
    00430   MKCOLOUR(0X5A595A59), // height 24
    00431   MKCOLOUR(0X5A595A5A), // height 25
    00432   MKCOLOUR(0X5A595A5A), // height 26
    00433   MKCOLOUR(0X5A5A5959), // height 27
    00434   MKCOLOUR(0X5A5A5959), // height 28
    00435   MKCOLOUR(0X5A5A595A), // height 29
    00436   MKCOLOUR(0X5A5A595A), // height 30
    00437   MKCOLOUR(0X5A5A5A59), // height 31
    00438   MKCOLOUR(0X5A5A5A59), // height 32
    00439   MKCOLOUR(0x5A5A5A5A), // height 33 // original smallmap color do not modify
    00440   MKCOLOUR(0x5A5A5A5A), // height 34 // original smallmap color do not modify
    00441   MKCOLOUR(0x5A5A5A5B), // height 35
    00442   MKCOLOUR(0x5A5A5A5B), // height 36
    00443   MKCOLOUR(0x5A5A5B5A), // height 37
    00444   MKCOLOUR(0x5A5A5B5A), // height 38
    00445   MKCOLOUR(0x5A5A5B5B), // height 39
    00446   MKCOLOUR(0x5A5A5B5B), // height 40
    00447   MKCOLOUR(0x5A5B5A5A), // height 41
    00448   MKCOLOUR(0x5A5B5A5A), // height 42
    00449   MKCOLOUR(0x5A5B5A5B), // height 43 // original smallmap color do not modify
    00450   MKCOLOUR(0x5A5B5A5B), // height 44 // original smallmap color do not modify
    00451   MKCOLOUR(0x5A5B5B5A), // height 45
    00452   MKCOLOUR(0x5A5B5B5A), // height 46
    00453   MKCOLOUR(0x5A5B5B5B), // height 47
    00454   MKCOLOUR(0x5A5B5B5B), // height 48
    00455   MKCOLOUR(0x5B5A5A5A), // height 49
    00456   MKCOLOUR(0x5B5A5A5A), // height 50
    00457   MKCOLOUR(0x5B5A5A5B), // height 51
    00458   MKCOLOUR(0x5B5A5A5B), // height 52
    00459   MKCOLOUR(0x5B5A5B5A), // height 53
    00460   MKCOLOUR(0x5B5A5B5A), // height 54
    00461   MKCOLOUR(0x5B5A5B5B), // height 55
    00462   MKCOLOUR(0x5B5A5B5B), // height 56
    00463   MKCOLOUR(0x5B5B5A5A), // height 57
    00464   MKCOLOUR(0x5B5B5A5A), // height 58
    00465   MKCOLOUR(0x5B5B5A5B), // height 59
    00466   MKCOLOUR(0x5B5B5A5B), // height 60
    00467   MKCOLOUR(0x5B5B5B5B), // height 61 // original smallmap color do not modify
    00468   MKCOLOUR(0x5B5B5B5B), // height 62 // original smallmap color do not modify
    00469   MKCOLOUR(0x5B5B5B5C), // height 63
    00470   MKCOLOUR(0x5B5B5B5C), // height 64
    00471   MKCOLOUR(0x5B5B5C5B), // height 65
    00472   MKCOLOUR(0x5B5B5C5B), // height 66
    00473   MKCOLOUR(0x5B5B5C5C), // height 67
    00474   MKCOLOUR(0x5B5B5C5C), // height 68
    00475   MKCOLOUR(0x5B5C5B5B), // height 69
    00476   MKCOLOUR(0x5B5C5B5B), // height 70
    00477   MKCOLOUR(0x5B5C5B5C), // height 71 // original smallmap color do not modify
    00478   MKCOLOUR(0x5B5C5B5C), // height 72 // original smallmap color do not modify
    00479   MKCOLOUR(0x5B5C5C5B), // height 73
    00480   MKCOLOUR(0x5B5C5C5B), // height 74
    00481   MKCOLOUR(0x5B5C5C5C), // height 75
    00482   MKCOLOUR(0x5B5C5C5C), // height 76
    00483   MKCOLOUR(0x5C5B5B5B), // height 77
    00484   MKCOLOUR(0x5C5B5B5B), // height 78
    00485   MKCOLOUR(0x5C5B5B5C), // height 79
    00486   MKCOLOUR(0x5C5B5B5C), // height 80
    00487   MKCOLOUR(0x5C5B5C5B), // height 81
    00488   MKCOLOUR(0x5C5B5C5B), // height 82
    00489   MKCOLOUR(0x5C5B5C5C), // height 83
    00490   MKCOLOUR(0x5C5B5C5C), // height 84
    00491   MKCOLOUR(0x5C5C5B5B), // height 85
    00492   MKCOLOUR(0x5C5C5B5B), // height 86
    00493   MKCOLOUR(0x5C5C5B5C), // height 87
    00494   MKCOLOUR(0x5C5C5B5C), // height 88
    00495   MKCOLOUR(0x5C5C5C5C), // height 89 // original smallmap color do not modify
    00496   MKCOLOUR(0x5C5C5C5C), // height 90 // original smallmap color do not modify
    00497   MKCOLOUR(0x5C5C5C5D), // height 91
    00498   MKCOLOUR(0x5C5C5C5D), // height 92
    00499   MKCOLOUR(0x5C5C5D5C), // height 93
    00500   MKCOLOUR(0x5C5C5D5C), // height 94
    00501   MKCOLOUR(0x5C5C5D5D), // height 95
    00502   MKCOLOUR(0x5C5C5D5D), // height 96
    00503   MKCOLOUR(0x5C5D5C5C), // height 97
    00504   MKCOLOUR(0x5C5D5C5C), // height 98
    00505   MKCOLOUR(0x5C5D5C5D), // height 99 // original smallmap color do not modify
    00506   MKCOLOUR(0x5C5D5C5D), // height 100 // original smallmap color do not modify
    00507   MKCOLOUR(0x5C5D5D5C), // height 101
    00508   MKCOLOUR(0x5C5D5D5C), // height 102
    00509   MKCOLOUR(0x5C5D5D5D), // height 103
    00510   MKCOLOUR(0x5C5D5D5D), // height 104
    00511   MKCOLOUR(0x5D5C5C5C), // height 105
    00512   MKCOLOUR(0x5D5C5C5C), // height 106
    00513   MKCOLOUR(0x5D5C5C5D), // height 107
    00514   MKCOLOUR(0x5D5C5C5D), // height 108
    00515   MKCOLOUR(0x5D5C5D5C), // height 109
    00516   MKCOLOUR(0x5D5C5D5C), // height 110
    00517   MKCOLOUR(0x5D5C5D5D), // height 111
    00518   MKCOLOUR(0x5D5C5D5D), // height 112
    00519   MKCOLOUR(0x5D5D5C5C), // height 113
    00520   MKCOLOUR(0x5D5D5C5C), // height 114
    00521   MKCOLOUR(0x5D5D5C5D), // height 115
    00522   MKCOLOUR(0x5D5D5C5D), // height 116
    00523   MKCOLOUR(0x5D5D5D5D), // height 117 // original smallmap color do not modify
    00524   MKCOLOUR(0x5D5D5D5D), // height 118 // original smallmap color do not modify
    00525   MKCOLOUR(0x5D5D5D5E), // height 119
    00526   MKCOLOUR(0x5D5D5D5E), // height 120
    00527   MKCOLOUR(0x5D5D5E5D), // height 121
    00528   MKCOLOUR(0x5D5D5E5D), // height 122
    00529   MKCOLOUR(0x5D5D5E5E), // height 123
    00530   MKCOLOUR(0x5D5D5E5E), // height 124
    00531   MKCOLOUR(0x5D5E5D5D), // height 125
    00532   MKCOLOUR(0x5D5E5D5D), // height 126
    00533   MKCOLOUR(0x5D5E5D5E), // height 127 // original smallmap color do not modify
    00534   MKCOLOUR(0x5D5E5D5E), // height 128 // original smallmap color do not modify
    00535   MKCOLOUR(0x5D5E5E5D), // height 129
    00536   MKCOLOUR(0x5D5E5E5D), // height 130
    00537   MKCOLOUR(0x5D5E5E5E), // height 131
    00538   MKCOLOUR(0x5D5E5E5E), // height 132
    00539   MKCOLOUR(0x5E5D5D5D), // height 133
    00540   MKCOLOUR(0x5E5D5D5D), // height 134
    00541   MKCOLOUR(0x5E5D5D5E), // height 135
    00542   MKCOLOUR(0x5E5D5D5E), // height 136
    00543   MKCOLOUR(0x5E5D5E5D), // height 137
    00544   MKCOLOUR(0x5E5D5E5D), // height 138
    00545   MKCOLOUR(0x5E5D5E5E), // height 139
    00546   MKCOLOUR(0x5E5D5E5E), // height 140
    00547   MKCOLOUR(0x5E5D5D5D), // height 141
    00548   MKCOLOUR(0x5E5D5D5D), // height 142
    00549   MKCOLOUR(0x5E5D5D5E), // height 143
    00550   MKCOLOUR(0x5E5D5D5E), // height 144
    00551   MKCOLOUR(0x5E5E5E5E), // height 145 // original smallmap color do not modify
    00552   MKCOLOUR(0x5E5E5E5E), // height 146 // original smallmap color do not modify
    00553   MKCOLOUR(0x5E5E5E5F), // height 147
    00554   MKCOLOUR(0x5E5E5E5F), // height 148
    00555   MKCOLOUR(0x5E5E5F5E), // height 149
    00556   MKCOLOUR(0x5E5E5F5E), // height 150
    00557   MKCOLOUR(0x5E5E5F5F), // height 151
    00558   MKCOLOUR(0x5E5E5F5F), // height 152
    00559   MKCOLOUR(0x5E5F5E5E), // height 153
    00560   MKCOLOUR(0x5E5F5E5E), // height 154
    00561   MKCOLOUR(0x5E5F5E5F), // height 155 // original smallmap color do not modify
    00562   MKCOLOUR(0x5E5F5E5F), // height 156 // original smallmap color do not modify
    00563   MKCOLOUR(0x5E5F5F5E), // height 157
    00564   MKCOLOUR(0x5E5F5F5E), // height 158
    00565   MKCOLOUR(0x5E5F5F5F), // height 159
    00566   MKCOLOUR(0x5E5F5F5F), // height 160
    00567   MKCOLOUR(0x5F5E5E5E), // height 161
    00568   MKCOLOUR(0x5F5E5E5E), // height 162
    00569   MKCOLOUR(0x5F5E5E5F), // height 163
    00570   MKCOLOUR(0x5F5E5E5F), // height 164
    00571   MKCOLOUR(0x5F5E5F5E), // height 165
    00572   MKCOLOUR(0x5F5E5F5E), // height 166
    00573   MKCOLOUR(0x5F5E5F5F), // height 167
    00574   MKCOLOUR(0x5F5E5F5F), // height 168
    00575   MKCOLOUR(0x5F5F5E5E), // height 169
    00576   MKCOLOUR(0x5F5F5E5E), // height 170
    00577   MKCOLOUR(0x5F5F5E5F), // height 171
    00578   MKCOLOUR(0x5F5F5E5F), // height 172
    00579   MKCOLOUR(0x5F5F5F5F), // height 173 // original smallmap color do not modify
    00580   MKCOLOUR(0x5F5F5F5F), // height 174 // original smallmap color do not modify
    00581   MKCOLOUR(0x5F5F5F1F), // height 175
    00582   MKCOLOUR(0x5F5F5F1F), // height 176
    00583   MKCOLOUR(0x5F5F1F5F), // height 177
    00584   MKCOLOUR(0x5F5F1F5F), // height 178
    00585   MKCOLOUR(0x5F5F1F1F), // height 179
    00586   MKCOLOUR(0x5F5F1F1F), // height 180
    00587   MKCOLOUR(0x5F1F5F1F), // height 181 // original smallmap color do not modify
    00588   MKCOLOUR(0x5F1F5F1F), // height 182 // original smallmap color do not modify
    00589 // pale greens need finetuning ?
    00590   MKCOLOUR(0x5F1F1F1F), // height 183
    00591   MKCOLOUR(0x5F1F1F1F), // height 184
    00592   MKCOLOUR(0x1F5F5F5F), // height 185
    00593   MKCOLOUR(0x1F5F5F5F), // height 186
    00594   MKCOLOUR(0x1F5F5F1F), // height 187
    00595   MKCOLOUR(0x1F5F5F1F), // height 188
    00596   MKCOLOUR(0x1F5F1F5F), // height 189
    00597   MKCOLOUR(0x1F5F1F5F), // height 190
    00598   MKCOLOUR(0x1F5F1F1F), // height 191
    00599   MKCOLOUR(0x1F5F1F1F), // height 192
    00600   MKCOLOUR(0x1F1F5F5F), // height 193
    00601   MKCOLOUR(0x1F1F5F5F), // height 194
    00602   MKCOLOUR(0x1F1F5F1F), // height 195
    00603   MKCOLOUR(0x1F1F5F1F), // height 196
    00604   MKCOLOUR(0x1F1F1F5F), // height 197
    00605   MKCOLOUR(0x1F1F1F5F), // height 198
    00606 //fine tune pale greens untill here ?
    00607   MKCOLOUR(0x1F1F1F1F), // height 199 // original smallmap color do not modify
    00608   MKCOLOUR(0x1F1F1F1F), // height 200 // original smallmap color do not modify
    00609   MKCOLOUR(0x1F1F1F27), // height 201
    00610   MKCOLOUR(0x1F1F1F27), // height 202
    00611   MKCOLOUR(0x1F1F271F), // height 203
    00612   MKCOLOUR(0x1F1F271F), // height 204
    00613   MKCOLOUR(0x1F1F2727), // height 205
    00614   MKCOLOUR(0x1F1F2727), // height 206
    00615   MKCOLOUR(0x1F271F1F), // height 207
    00616   MKCOLOUR(0x1F271F1F), // height 208
    00617   MKCOLOUR(0x1F271F27), // height 209 // original smallmap color do not modify
    00618   MKCOLOUR(0x1F271F27), // height 210 // original smallmap color do not modify
    00619   MKCOLOUR(0x1F272727), // height 211
    00620   MKCOLOUR(0x1F272727), // height 212
    00621   MKCOLOUR(0x271F1F1F), // height 213
    00622   MKCOLOUR(0x271F1F1F), // height 214
    00623   MKCOLOUR(0x271F1F27), // height 215
    00624   MKCOLOUR(0x271F1F27), // height 216
    00625   MKCOLOUR(0x271F271F), // height 217
    00626   MKCOLOUR(0x271F271F), // height 218
    00627   MKCOLOUR(0x271F2727), // height 219
    00628   MKCOLOUR(0x271F2727), // height 220
    00629   MKCOLOUR(0x27271F1F), // height 221
    00630   MKCOLOUR(0x27271F1F), // height 222
    00631   MKCOLOUR(0x27271F27), // height 223
    00632   MKCOLOUR(0x27271F27), // height 224
    00633   MKCOLOUR(0x2727271F), // height 225
    00634   MKCOLOUR(0x2727271F), // height 226
    00635   MKCOLOUR(0x27272727), // height 227 // original smallmap color do not modify
    00636   MKCOLOUR(0x27272727), // height 228 // original smallmap color do not modify
    00637     /* Above and below the same color. I know. It was like that before I arrived. I prefer extending over modifying, it stays. */
    00638   MKCOLOUR(0x27272727), // height 229 // original smallmap color do not modify
    00639   MKCOLOUR(0x27272727), // height 230 // original smallmap color do not modify
    00640   /* Purple top */
    00641   MKCOLOUR(0x1F27AF27), // height 231
    00642   MKCOLOUR(0x1F27AF27), // height 232
    00643   MKCOLOUR(0x1F274FAF), // height 233
    00644   MKCOLOUR(0x1F274FAF), // height 234
    00645   MKCOLOUR(0x4F274FAF), // height 235
    00646   MKCOLOUR(0x4F274FAF), // height 236
    00647   MKCOLOUR(0x4FAF1FAF), // height 237
    00648   MKCOLOUR(0x4FAF1FAF), // height 238
    00649   MKCOLOUR(0x4F2727AF), // height 239
    00650   MKCOLOUR(0x4F2727AF), // height 240
    00651   MKCOLOUR(0x4F27AF27), // height 241
    00652   MKCOLOUR(0x4F27AF27), // height 242
    00653   MKCOLOUR(0x4F27AFAF), // height 243
    00654   MKCOLOUR(0x4F27AFAF), // height 244
    00655   MKCOLOUR(0x4FAF2727), // height 245
    00656   MKCOLOUR(0x4FAF2727), // height 246
    00657   MKCOLOUR(0x4FAF27AF), // height 247
    00658   MKCOLOUR(0x4FAF27AF), // height 248
    00659   MKCOLOUR(0x4FAFAF27), // height 249
    00660   MKCOLOUR(0x4FAFAF27), // height 250
    00661   MKCOLOUR(0x4FAFAFAF), // height 251
    00662   MKCOLOUR(0x4FAFAFAF), // height 252
    00663   MKCOLOUR(0x4FAFAFCF), // height 253
    00664   MKCOLOUR(0x4FAFAFCF), // height 254
    00665   MKCOLOUR(0x4FAFCFAF), // height 255
    00666   MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
    00667   /* Flashing test with current parameters no longer needed. */
    00668   //MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
    00669 };
    00670 assert_compile(lengthof(_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
    00671
    00676 static const uint32 _dark_green_map_heights_old[] = {
    00677   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    00678   MKCOLOUR_XXXX(0x60),
    00679   MKCOLOUR_XYXY(0x60, 0x61),
    00680   MKCOLOUR_XXXX(0x61),
    00681   MKCOLOUR_XYXY(0x61, 0x62),
    00682   MKCOLOUR_XXXX(0x62),
    00683   MKCOLOUR_XYXY(0x62, 0x63),
    00684   MKCOLOUR_XXXX(0x63),
    00685   MKCOLOUR_XYXY(0x63, 0x64),
    00686   MKCOLOUR_XXXX(0x64),
    00687   MKCOLOUR_XYXY(0x64, 0x65),
    00688   MKCOLOUR_XXXX(0x65),
    00689   MKCOLOUR_XYXY(0x65, 0x66),
    00690   MKCOLOUR_XXXX(0x66),
    00691   MKCOLOUR_XYXY(0x66, 0x67),
    00692   MKCOLOUR_XXXX(0x67),
    00693   MKCOLOUR_XXXX(0x67),
    00694 };
    00695 assert_compile(lengthof(_dark_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
    00696
    00702 static const uint32 _dark_green_map_heights_extended[] = {
    00703   /* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
    00704   //MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
    00705   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    00706   MKCOLOUR(0x60606060), // height 1 // original smallmap color do not modify
    00707   MKCOLOUR(0x60606060),
    00708   MKCOLOUR(0x60606061), // height 3
    00709   MKCOLOUR(0x60606061),
    00710   MKCOLOUR(0x60606160), // height 5
    00711   MKCOLOUR(0x60606160),
    00712   MKCOLOUR(0x60606161), // height 7
    00713   MKCOLOUR(0x60606161),
    00714   MKCOLOUR(0x60616060), // height 9
    00715   MKCOLOUR(0x60616060),
    00716   MKCOLOUR(0x60616061), // height 11 // original smallmap color do not modify
    00717   MKCOLOUR(0x60616061),
    00718   MKCOLOUR(0x60616160), // height 13
    00719   MKCOLOUR(0x60616160),
    00720   MKCOLOUR(0x60616161), // height 15
    00721   MKCOLOUR(0x60616161),
    00722   MKCOLOUR(0x61606060), // height 17
    00723   MKCOLOUR(0x61606060),
    00724   MKCOLOUR(0x61606061), // height 19
    00725   MKCOLOUR(0x61606061),
    00726   MKCOLOUR(0x61606160), // height 21
    00727   MKCOLOUR(0x61606160),
    00728   MKCOLOUR(0x61606161), // height 23
    00729   MKCOLOUR(0x61606161),
    00730   MKCOLOUR(0x61616060), // height 25
    00731   MKCOLOUR(0x61616060),
    00732   MKCOLOUR(0x61616061), // height 27
    00733   MKCOLOUR(0x61616061),
    00734   MKCOLOUR(0x61616160), // height 29
    00735   MKCOLOUR(0x61616160),
    00736   MKCOLOUR(0x61616161), // height 31 // original smallmap color do not modify
    00737   MKCOLOUR(0x61616161),
    00738   MKCOLOUR(0x61616162), // height 33
    00739   MKCOLOUR(0x61616162),
    00740   MKCOLOUR(0x61616261), // height 35
    00741   MKCOLOUR(0x61616261),
    00742   MKCOLOUR(0x61616262), // height 37
    00743   MKCOLOUR(0x61616262),
    00744   MKCOLOUR(0x61626161), // height 39
    00745   MKCOLOUR(0x61626161),
    00746   MKCOLOUR(0x61626162), // height 41 // original smallmap color do not modify
    00747   MKCOLOUR(0x61626162),
    00748   MKCOLOUR(0x61626261), // height 43
    00749   MKCOLOUR(0x61626261),
    00750   MKCOLOUR(0x61626262), // height 45
    00751   MKCOLOUR(0x61626262),
    00752   MKCOLOUR(0x62616161), // height 47
    00753   MKCOLOUR(0x62616161),
    00754   MKCOLOUR(0x62616162), // height 49
    00755   MKCOLOUR(0x62616162),
    00756   MKCOLOUR(0x62616261), // height 51
    00757   MKCOLOUR(0x62616261),
    00758   MKCOLOUR(0x62616262), // height 53
    00759   MKCOLOUR(0x62616262),
    00760   MKCOLOUR(0x62626161), // height 55
    00761   MKCOLOUR(0x62626161),
    00762   MKCOLOUR(0x62626162), // height 57
    00763   MKCOLOUR(0x62626162),
    00764   MKCOLOUR(0x62626261), // height 59
    00765   MKCOLOUR(0x62626261),
    00766   MKCOLOUR(0x62626262), // height 61 // original smallmap color do not modify
    00767   MKCOLOUR(0x62626262),
    00768   MKCOLOUR(0x62626263), // height 63
    00769   MKCOLOUR(0x62626263),
    00770   MKCOLOUR(0x62626362), // height 65
    00771   MKCOLOUR(0x62626362),
    00772   MKCOLOUR(0x62626363), // height 67
    00773   MKCOLOUR(0x62626363),
    00774   MKCOLOUR(0x62636262), // height 69
    00775   MKCOLOUR(0x62636262),
    00776   MKCOLOUR(0x62636263), // height 71 // original smallmap color do not modify
    00777   MKCOLOUR(0x62636263),
    00778   MKCOLOUR(0x62636362), // height 73
    00779   MKCOLOUR(0x62636362),
    00780   MKCOLOUR(0x62636363), // height 75
    00781   MKCOLOUR(0x62636363),
    00782   MKCOLOUR(0x63626262), // height 77
    00783   MKCOLOUR(0x63626262),
    00784   MKCOLOUR(0x63626263), // height 79
    00785   MKCOLOUR(0x63626263),
    00786   MKCOLOUR(0x63626362), // height 81
    00787   MKCOLOUR(0x63626362),
    00788   MKCOLOUR(0x63626363), // height 83
    00789   MKCOLOUR(0x63626363),
    00790   MKCOLOUR(0x63636262), // height 85
    00791   MKCOLOUR(0x63636262),
    00792   MKCOLOUR(0x63636263), // height 87
    00793   MKCOLOUR(0x63636263),
    00794   MKCOLOUR(0x63636362), // height 89
    00795   MKCOLOUR(0x63636362),
    00796   MKCOLOUR(0x63636363), // height 91 // original smallmap color do not modify
    00797   MKCOLOUR(0x63636363),
    00798   MKCOLOUR(0x63636364), // height 93
    00799   MKCOLOUR(0x63636364),
    00800   MKCOLOUR(0x63636463), // height 95
    00801   MKCOLOUR(0x63636463),
    00802   MKCOLOUR(0x63636464), // height 97
    00803   MKCOLOUR(0x63636464),
    00804   MKCOLOUR(0x63646363), // height 99
    00805   MKCOLOUR(0x63646363),
    00806   MKCOLOUR(0x63646364), // height 101 // original smallmap color do not modify
    00807   MKCOLOUR(0x63646364),
    00808   MKCOLOUR(0x63646463), // height 103
    00809   MKCOLOUR(0x63646463),
    00810   MKCOLOUR(0x63646464), // height 105
    00811   MKCOLOUR(0x63646464),
    00812   MKCOLOUR(0x64636363), // height 107
    00813   MKCOLOUR(0x64636363),
    00814   MKCOLOUR(0x64636364), // height 109
    00815   MKCOLOUR(0x64636364),
    00816   MKCOLOUR(0x64636463), // height 111
    00817   MKCOLOUR(0x64636463),
    00818   MKCOLOUR(0x64636464), // height 113
    00819   MKCOLOUR(0x64636464),
    00820   MKCOLOUR(0x64646363), // height 115
    00821   MKCOLOUR(0x64646363),
    00822   MKCOLOUR(0x64646364), // height 117
    00823   MKCOLOUR(0x64646364),
    00824   MKCOLOUR(0x64646463), // height 119
    00825   MKCOLOUR(0x64646463),
    00826   MKCOLOUR(0x64646464), // height 121 // original smallmap color do not modify
    00827   MKCOLOUR(0x64646464),
    00828   MKCOLOUR(0x64646465), // height 123
    00829   MKCOLOUR(0x64646465),
    00830   MKCOLOUR(0x64646564), // height 125
    00831   MKCOLOUR(0x64646564),
    00832   MKCOLOUR(0x64646565), // height 127
    00833   MKCOLOUR(0x64646565),
    00834   MKCOLOUR(0x64656464), // height 129
    00835   MKCOLOUR(0x64656464),
    00836   MKCOLOUR(0x64656465), // height 131 // original smallmap color do not modify
    00837   MKCOLOUR(0x64656465),
    00838   MKCOLOUR(0x64656564), // height 133
    00839   MKCOLOUR(0x64656564),
    00840   MKCOLOUR(0x64656565), // height 135
    00841   MKCOLOUR(0x64656565),
    00842   MKCOLOUR(0x65646464), // height 137
    00843   MKCOLOUR(0x65646464),
    00844   MKCOLOUR(0x65646465), // height 139
    00845   MKCOLOUR(0x65646465),
    00846   MKCOLOUR(0x65646564), // height 141
    00847   MKCOLOUR(0x65646564),
    00848   MKCOLOUR(0x65646565), // height 143
    00849   MKCOLOUR(0x65646565),
    00850   MKCOLOUR(0x65656464), // height 145
    00851   MKCOLOUR(0x65656464),
    00852   MKCOLOUR(0x65656465), // height 147
    00853   MKCOLOUR(0x65656465),
    00854   MKCOLOUR(0x65656564), // height 149
    00855   MKCOLOUR(0x65656564),
    00856   MKCOLOUR(0x65656565), // height 151 // original smallmap color do not modify
    00857   MKCOLOUR(0x65656565),
    00858   MKCOLOUR(0x65656566), // height 153
    00859   MKCOLOUR(0x65656566),
    00860   MKCOLOUR(0x65656665), // height 155
    00861   MKCOLOUR(0x65656665),
    00862   MKCOLOUR(0x65656666), // height 157
    00863   MKCOLOUR(0x65656666),
    00864   MKCOLOUR(0x65666565), // height 159
    00865   MKCOLOUR(0x65666565),
    00866   MKCOLOUR(0x65666566), // height 161 // original smallmap color do not modify
    00867   MKCOLOUR(0x65666566),
    00868   MKCOLOUR(0x65666665), // height 163
    00869   MKCOLOUR(0x65666665),
    00870   MKCOLOUR(0x65666666), // height 165
    00871   MKCOLOUR(0x65666666),
    00872   MKCOLOUR(0x66656565), // height 167
    00873   MKCOLOUR(0x66656565),
    00874   MKCOLOUR(0x66656566), // height 169
    00875   MKCOLOUR(0x66656566),
    00876   MKCOLOUR(0x66656665), // height 171
    00877   MKCOLOUR(0x66656665),
    00878   MKCOLOUR(0x66656666), // height 173
    00879   MKCOLOUR(0x66656666),
    00880   MKCOLOUR(0x66666565), // height 175
    00881   MKCOLOUR(0x66666565),
    00882   MKCOLOUR(0x66666566), // height 177
    00883   MKCOLOUR(0x66666566),
    00884   MKCOLOUR(0x66666665), // height 179
    00885   MKCOLOUR(0x66666665),
    00886   MKCOLOUR(0x66666666), // height 181 // original smallmap color do not modify
    00887   MKCOLOUR(0x66666666),
    00888   MKCOLOUR(0x66666667), // height 183
    00889   MKCOLOUR(0x66666667),
    00890   MKCOLOUR(0x66666766), // height 185
    00891   MKCOLOUR(0x66666766),
    00892   MKCOLOUR(0x66666767), // height 187
    00893   MKCOLOUR(0x66666767),
    00894   MKCOLOUR(0x66676666), // height 189
    00895   MKCOLOUR(0x66676666),
    00896   MKCOLOUR(0x66676667), // height 191 // original smallmap color do not modify
    00897   MKCOLOUR(0x66676667),
    00898   MKCOLOUR(0x66676766), // height 193
    00899   MKCOLOUR(0x66676766),
    00900   MKCOLOUR(0x66676767), // height 195
    00901   MKCOLOUR(0x66676767),
    00902   MKCOLOUR(0x67676767), // height 197 // original smallmap color do not modify
    00903   MKCOLOUR(0x67676767),
    00904
    00905 // TODO: Extend. read: replace dummy (copied) colurs below
    00906
    00907 //  MKCOLOUR(0x67676768), // browns or something do not use untill ...
    00908 //  MKCOLOUR(0x67676868),
    00909 //  MKCOLOUR(0x67686868),
    00910 //  MKCOLOUR(0x68686868),
    00911 //  MKCOLOUR(0x68686869),
    00912 //  MKCOLOUR(0x69686869),
    00913 //  MKCOLOUR(0x68686969),
    00914 //  MKCOLOUR(0x68696969),
    00915 //  MKCOLOUR(0x69696969),
    00916 //  MKCOLOUR(0x6969696A),
    00917 //  MKCOLOUR(0x69A96A6A),
    00918 //  MKCOLOUR(0x6A6A6A6A),
    00919 //  MKCOLOUR(0x6A6A6A6B),
    00920 //  MKCOLOUR(0x6A6A6B6B),
    00921 //  MKCOLOUR(0x6A6B6B6B),
    00922 //  MKCOLOUR(0x6B6B6B6B), // ... here and probably a little further.
    00923
    00924   MKCOLOUR(0x67676767), // height 199
    00925   MKCOLOUR(0x67676767),
    00926   MKCOLOUR(0x67676767), // height 201
    00927   MKCOLOUR(0x67676767),
    00928   MKCOLOUR(0x67676767), // height 203
    00929   MKCOLOUR(0x67676767),
    00930   MKCOLOUR(0x67676767), // height 205
    00931   MKCOLOUR(0x67676767),
    00932   MKCOLOUR(0x67676767), // height 207
    00933   MKCOLOUR(0x67676767),
    00934   MKCOLOUR(0x67676767), // height 209
    00935   MKCOLOUR(0x67676767),
    00936   MKCOLOUR(0x67676767), // height 211
    00937   MKCOLOUR(0x67676767),
    00938   MKCOLOUR(0x67676767), // height 213
    00939   MKCOLOUR(0x67676767),
    00940   MKCOLOUR(0x67676767), // height 215
    00941   MKCOLOUR(0x67676767),
    00942   MKCOLOUR(0x67676767), // height 217
    00943   MKCOLOUR(0x67676767),
    00944   MKCOLOUR(0x67676767), // height 219
    00945   MKCOLOUR(0x67676767),
    00946   MKCOLOUR(0x67676767), // height 221
    00947   MKCOLOUR(0x67676767),
    00948   MKCOLOUR(0x67676767), // height 223
    00949   MKCOLOUR(0x67676767),
    00950   MKCOLOUR(0x67676767), // height 225
    00951   MKCOLOUR(0x67676767),
    00952   MKCOLOUR(0x67676767), // height 227
    00953   MKCOLOUR(0x67676767),
    00954   MKCOLOUR(0x67676767), // height 229
    00955   MKCOLOUR(0x67676767),
    00956
    00957 // TODO: extend untill here
    00958
    00959   /* purple top */
    00960   MKCOLOUR(0x1F27AF27), // height 231
    00961   MKCOLOUR(0x1F27AF27), // height 232
    00962   MKCOLOUR(0x1F274FAF), // height 233
    00963   MKCOLOUR(0x1F274FAF), // height 234
    00964   MKCOLOUR(0x4F274FAF), // height 235
    00965   MKCOLOUR(0x4F274FAF), // height 236
    00966   MKCOLOUR(0x4FAF1FAF), // height 237
    00967   MKCOLOUR(0x4FAF1FAF), // height 238
    00968   MKCOLOUR(0x4F2727AF), // height 239
    00969   MKCOLOUR(0x4F2727AF), // height 240
    00970   MKCOLOUR(0x4F27AF27), // height 241
    00971   MKCOLOUR(0x4F27AF27), // height 242
    00972   MKCOLOUR(0x4F27AFAF), // height 243
    00973   MKCOLOUR(0x4F27AFAF), // height 244
    00974   MKCOLOUR(0x4FAF2727), // height 245
    00975   MKCOLOUR(0x4FAF2727), // height 246
    00976   MKCOLOUR(0x4FAF27AF), // height 247
    00977   MKCOLOUR(0x4FAF27AF), // height 248
    00978   MKCOLOUR(0x4FAFAF27), // height 249
    00979   MKCOLOUR(0x4FAFAF27), // height 250
    00980   MKCOLOUR(0x4FAFAFAF), // height 251
    00981   MKCOLOUR(0x4FAFAFAF), // height 252
    00982   MKCOLOUR(0x4FAFAFCF), // height 253
    00983   MKCOLOUR(0x4FAFAFCF), // height 254
    00984   MKCOLOUR(0x4FAFCFAF), // height 255
    00985   MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
    00986   /* Flashing test with current parameters no longer needed. */
    00987   //MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
    00988 };
    00989 assert_compile(lengthof(_dark_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
    00990
    00995 static const uint32 _violet_map_heights_old[] = {
    00996   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    00997   MKCOLOUR_XXXX(0x80),
    00998   MKCOLOUR_XYXY(0x80, 0x81),
    00999   MKCOLOUR_XXXX(0x81),
    01000   MKCOLOUR_XYXY(0x81, 0x82),
    01001   MKCOLOUR_XXXX(0x82),
    01002   MKCOLOUR_XYXY(0x82, 0x83),
    01003   MKCOLOUR_XXXX(0x83),
    01004   MKCOLOUR_XYXY(0x83, 0x84),
    01005   MKCOLOUR_XXXX(0x84),
    01006   MKCOLOUR_XYXY(0x84, 0x85),
    01007   MKCOLOUR_XXXX(0x85),
    01008   MKCOLOUR_XYXY(0x85, 0x86),
    01009   MKCOLOUR_XXXX(0x86),
    01010   MKCOLOUR_XYXY(0x86, 0x87),
    01011   MKCOLOUR_XXXX(0x87),
    01012   MKCOLOUR_XXXX(0x87),
    01013 };
    01014 assert_compile(lengthof(_violet_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
    01015
    01021 static const uint32 _violet_map_heights_extended[] = {
    01022   /* First two colours are action colours.(First commented out, first we need level -1 (and underwater tunnels)) */
    01023   //MKCOLOUR(0xdcdcdcdc), // Nice flashy colour, darkblue. (Do not use above level 1. (second colour)) (I keep it here to become level -1 ground tile (not flooded) (For now: To see its full effect, use this as second color.Then imagine at level -1.))
    01024   MKCOLOUR(0x04dcdcdc), // Action colour, flashing purple. This is for level zero(Not flooded) !! Flooding danger !! Not yet water. (When level -1 will be possible: Will provide for a nice flooding_danger_area_border_flash in combination witch previous colour, similar to the waves at water borders.)
    01025   MKCOLOUR(0x80808080), // height 1 // original smallmap color do not modify
    01026   MKCOLOUR(0x80808080),
    01027   MKCOLOUR(0x80808081), // height 3
    01028   MKCOLOUR(0x80808081),
    01029   MKCOLOUR(0x80808180), // height 5
    01030   MKCOLOUR(0x80808180),
    01031   MKCOLOUR(0x80808181), // height 7
    01032   MKCOLOUR(0x80808181),
    01033   MKCOLOUR(0x80818080), // height 9
    01034   MKCOLOUR(0x80818080),
    01035   MKCOLOUR(0x80818081), // height 11 // original smallmap color do not modify
    01036   MKCOLOUR(0x80818081),
    01037   MKCOLOUR(0x80818180), // height 13
    01038   MKCOLOUR(0x80818180),
    01039   MKCOLOUR(0x80818181), // height 15
    01040   MKCOLOUR(0x80818181),
    01041   MKCOLOUR(0x81808080), // height 17
    01042   MKCOLOUR(0x81808080),
    01043   MKCOLOUR(0x81808081), // height 19
    01044   MKCOLOUR(0x81808081),
    01045   MKCOLOUR(0x81808180), // height 21
    01046   MKCOLOUR(0x81808180),
    01047   MKCOLOUR(0x81808181), // height 23
    01048   MKCOLOUR(0x81808181),
    01049   MKCOLOUR(0x81818080), // height 25
    01050   MKCOLOUR(0x81818080),
    01051   MKCOLOUR(0x81818081), // height 27
    01052   MKCOLOUR(0x81818081),
    01053   MKCOLOUR(0x81818180), // height 29
    01054   MKCOLOUR(0x81818180),
    01055   MKCOLOUR(0x81818181), // height 31 // original smallmap color do not modify
    01056   MKCOLOUR(0x81818181),
    01057   MKCOLOUR(0x81818182), // height 33
    01058   MKCOLOUR(0x81818182),
    01059   MKCOLOUR(0x81818281), // height 35
    01060   MKCOLOUR(0x81818281),
    01061   MKCOLOUR(0x81818282), // height 37
    01062   MKCOLOUR(0x81818282),
    01063   MKCOLOUR(0x81828181), // height 39
    01064   MKCOLOUR(0x81828181),
    01065   MKCOLOUR(0x81828182), // height 41 // original smallmap color do not modify
    01066   MKCOLOUR(0x81828182),
    01067   MKCOLOUR(0x81828281), // height 43
    01068   MKCOLOUR(0x81828281),
    01069   MKCOLOUR(0x81828282), // height 45
    01070   MKCOLOUR(0x81828282),
    01071   MKCOLOUR(0x82818181), // height 47
    01072   MKCOLOUR(0x82818181),
    01073   MKCOLOUR(0x82818182), // height 49
    01074   MKCOLOUR(0x82818182),
    01075   MKCOLOUR(0x82818281), // height 51
    01076   MKCOLOUR(0x82818281),
    01077   MKCOLOUR(0x82818282), // height 53
    01078   MKCOLOUR(0x82818282),
    01079   MKCOLOUR(0x82828181), // height 55
    01080   MKCOLOUR(0x82828181),
    01081   MKCOLOUR(0x82828182), // height 57
    01082   MKCOLOUR(0x82828182),
    01083   MKCOLOUR(0x82828281), // height 59
    01084   MKCOLOUR(0x82828281),
    01085   MKCOLOUR(0x82828282), // height 61 // original smallmap color do not modify
    01086   MKCOLOUR(0x82828282),
    01087   MKCOLOUR(0x82828283), // height 63
    01088   MKCOLOUR(0x82828283),
    01089   MKCOLOUR(0x82828382), // height 65
    01090   MKCOLOUR(0x82828382),
    01091   MKCOLOUR(0x82828383), // height 67
    01092   MKCOLOUR(0x82828383),
    01093   MKCOLOUR(0x82838282), // height 69
    01094   MKCOLOUR(0x82838282),
    01095   MKCOLOUR(0x82838283), // height 71 // original smallmap color do not modify
    01096   MKCOLOUR(0x82838283),
    01097   MKCOLOUR(0x82838382), // height 73
    01098   MKCOLOUR(0x82838382),
    01099   MKCOLOUR(0x82838383), // height 75
    01100   MKCOLOUR(0x82838383),
    01101   MKCOLOUR(0x83828282), // height 77
    01102   MKCOLOUR(0x83828282),
    01103   MKCOLOUR(0x83828283), // height 79
    01104   MKCOLOUR(0x83828283),
    01105   MKCOLOUR(0x83828382), // height 81
    01106   MKCOLOUR(0x83828382),
    01107   MKCOLOUR(0x83828383), // height 83
    01108   MKCOLOUR(0x83828383),
    01109   MKCOLOUR(0x83838282), // height 85
    01110   MKCOLOUR(0x83838282),
    01111   MKCOLOUR(0x83838283), // height 87
    01112   MKCOLOUR(0x83838283),
    01113   MKCOLOUR(0x83838382), // height 89
    01114   MKCOLOUR(0x83838382),
    01115   MKCOLOUR(0x83838383), // height 91 // original smallmap color do not modify
    01116   MKCOLOUR(0x83838383),
    01117   MKCOLOUR(0x83838384), // height 93
    01118   MKCOLOUR(0x83838384),
    01119   MKCOLOUR(0x83838483), // height 95
    01120   MKCOLOUR(0x83838483),
    01121   MKCOLOUR(0x83838484), // height 97
    01122   MKCOLOUR(0x83838484),
    01123   MKCOLOUR(0x83848383), // height 99
    01124   MKCOLOUR(0x83848383),
    01125   MKCOLOUR(0x83848384), // height 101 // original smallmap color do not modify
    01126   MKCOLOUR(0x83848384),
    01127   MKCOLOUR(0x83848483), // height 103
    01128   MKCOLOUR(0x83848483),
    01129   MKCOLOUR(0x83848484), // height 105
    01130   MKCOLOUR(0x83848484),
    01131   MKCOLOUR(0x84838383), // height 107
    01132   MKCOLOUR(0x84838383),
    01133   MKCOLOUR(0x84838384), // height 109
    01134   MKCOLOUR(0x84838384),
    01135   MKCOLOUR(0x84838483), // height 111
    01136   MKCOLOUR(0x84838483),
    01137   MKCOLOUR(0x84838484), // height 113
    01138   MKCOLOUR(0x84838484),
    01139   MKCOLOUR(0x84848383), // height 115
    01140   MKCOLOUR(0x84848383),
    01141   MKCOLOUR(0x84848384), // height 117
    01142   MKCOLOUR(0x84848384),
    01143   MKCOLOUR(0x84848483), // height 119
    01144   MKCOLOUR(0x84848483),
    01145   MKCOLOUR(0x84848484), // height 121 // original smallmap color do not modify
    01146   MKCOLOUR(0x84848484),
    01147   MKCOLOUR(0x84848485), // height 123
    01148   MKCOLOUR(0x84848485),
    01149   MKCOLOUR(0x84848584), // height 125
    01150   MKCOLOUR(0x84848584),
    01151   MKCOLOUR(0x84848585), // height 127
    01152   MKCOLOUR(0x84848585),
    01153   MKCOLOUR(0x84858484), // height 129
    01154   MKCOLOUR(0x84858484),
    01155   MKCOLOUR(0x84858485), // height 131 // original smallmap color do not modify
    01156   MKCOLOUR(0x84858485),
    01157   MKCOLOUR(0x84858584), // height 133
    01158   MKCOLOUR(0x84858584),
    01159   MKCOLOUR(0x84858585), // height 135
    01160   MKCOLOUR(0x84858585),
    01161   MKCOLOUR(0x85848484), // height 137
    01162   MKCOLOUR(0x85848484),
    01163   MKCOLOUR(0x85848485), // height 139
    01164   MKCOLOUR(0x85848485),
    01165   MKCOLOUR(0x85848584), // height 141
    01166   MKCOLOUR(0x85848584),
    01167   MKCOLOUR(0x85848585), // height 143
    01168   MKCOLOUR(0x85848585),
    01169   MKCOLOUR(0x85858484), // height 145
    01170   MKCOLOUR(0x85858484),
    01171   MKCOLOUR(0x85858485), // height 147
    01172   MKCOLOUR(0x85858485),
    01173   MKCOLOUR(0x85858584), // height 149
    01174   MKCOLOUR(0x85858584),
    01175   MKCOLOUR(0x85858585), // height 151 // original smallmap color do not modify
    01176   MKCOLOUR(0x85858585),
    01177   MKCOLOUR(0x85858586), // height 153
    01178   MKCOLOUR(0x85858586),
    01179   MKCOLOUR(0x85858685), // height 155
    01180   MKCOLOUR(0x85858685),
    01181   MKCOLOUR(0x85858686), // height 157
    01182   MKCOLOUR(0x85858686),
    01183   MKCOLOUR(0x85868585), // height 159
    01184   MKCOLOUR(0x85868585),
    01185   MKCOLOUR(0x85868586), // height 161 // original smallmap color do not modify
    01186   MKCOLOUR(0x85868586),
    01187   MKCOLOUR(0x85868685), // height 163
    01188   MKCOLOUR(0x85868685),
    01189   MKCOLOUR(0x85868686), // height 165
    01190   MKCOLOUR(0x85868686),
    01191   MKCOLOUR(0x85868585), // height 167
    01192   MKCOLOUR(0x85868585),
    01193   MKCOLOUR(0x85868586), // height 169
    01194   MKCOLOUR(0x85868586),
    01195   MKCOLOUR(0x85868685), // height 171
    01196   MKCOLOUR(0x85868685),
    01197   MKCOLOUR(0x85868686), // height 173
    01198   MKCOLOUR(0x85868686),
    01199   MKCOLOUR(0x86868585), // height 175
    01200   MKCOLOUR(0x86868585),
    01201   MKCOLOUR(0x86868586), // height 177
    01202   MKCOLOUR(0x86868586),
    01203   MKCOLOUR(0x86868685), // height 179
    01204   MKCOLOUR(0x86868685),
    01205   MKCOLOUR(0x86868686), // height 181 // original smallmap color do not modify
    01206   MKCOLOUR(0x86868686),
    01207   MKCOLOUR(0x86868687), // height 183
    01208   MKCOLOUR(0x86868687),
    01209   MKCOLOUR(0x86868786), // height 185
    01210   MKCOLOUR(0x86868786),
    01211   MKCOLOUR(0x86868787), // height 187
    01212   MKCOLOUR(0x86868787),
    01213   MKCOLOUR(0x86878686), // height 189
    01214   MKCOLOUR(0x86878686),
    01215   MKCOLOUR(0x86878687), // height 191 // original smallmap color do not modify
    01216   MKCOLOUR(0x86878687),
    01217   MKCOLOUR(0x86878786), // height 193
    01218   MKCOLOUR(0x86878786),
    01219   MKCOLOUR(0x86878787), // height 195
    01220   MKCOLOUR(0x86878787),
    01221   MKCOLOUR(0x87868686), // height 197
    01222   MKCOLOUR(0x87868686),
    01223   MKCOLOUR(0x87868687), // height 199
    01224   MKCOLOUR(0x87868687),
    01225   MKCOLOUR(0x87868786), // height 201
    01226   MKCOLOUR(0x87868786),
    01227   MKCOLOUR(0x87868787), // height 203
    01228   MKCOLOUR(0x87868787),
    01229   MKCOLOUR(0x87878686), // height 205
    01230   MKCOLOUR(0x87878686),
    01231   MKCOLOUR(0x87878687), // height 207
    01232   MKCOLOUR(0x87878687),
    01233   MKCOLOUR(0x87878786), // height 209
    01234   MKCOLOUR(0x87878786),
    01235   MKCOLOUR(0x87878787), // height 211 // original smallmap color do not modify
    01236   MKCOLOUR(0x87878787),
    01237   MKCOLOUR(0x87878787), // height 213 // original smallmap color do not modify
    01238   MKCOLOUR(0x87878787),
    01239
    01240 // TODO: Extend. read: replace dummy (copied) colurs below
    01241
    01242 //  MKCOLOUR(0x87878788), // don't use greys/blacks
    01243 //  MKCOLOUR(0x87878788),
    01244 //  MKCOLOUR(0x87878887),
    01245 //  MKCOLOUR(0x87878887),
    01246 //  MKCOLOUR(0x87878888),
    01247 //  MKCOLOUR(0x87878888),
    01248 //  MKCOLOUR(0x87888787),
    01249 //  MKCOLOUR(0x87888787),
    01250 //  MKCOLOUR(0x87888788),
    01251 //  MKCOLOUR(0x87888788),
    01252 //  MKCOLOUR(0x87888887),
    01253 //  MKCOLOUR(0x87888887),
    01254 //  MKCOLOUR(0x87888888),
    01255 //  MKCOLOUR(0x87888888),
    01256 //  MKCOLOUR(0x88878787),
    01257 //  MKCOLOUR(0x88878788),
    01258 //  MKCOLOUR(0x88878887),
    01259 //  MKCOLOUR(0x88878888),
    01260 //  MKCOLOUR(0x88888787),
    01261 //  MKCOLOUR(0x88888788),
    01262 //  MKCOLOUR(0x88888887),
    01263 //  MKCOLOUR(0x88888888), // dont't use untill here probaby a little further too
    01264
    01265   MKCOLOUR(0x87878787), // height 215
    01266   MKCOLOUR(0x87878787),
    01267   MKCOLOUR(0x87878787), // height 217
    01268   MKCOLOUR(0x87878787),
    01269   MKCOLOUR(0x87878787), // height 219
    01270   MKCOLOUR(0x87878787),
    01271   MKCOLOUR(0x87878787), // height 221
    01272   MKCOLOUR(0x87878787),
    01273   MKCOLOUR(0x87878787), // height 223
    01274   MKCOLOUR(0x87878787),
    01275   MKCOLOUR(0x87878787), // height 225
    01276   MKCOLOUR(0x87878787),
    01277   MKCOLOUR(0x87878787), // height 227
    01278   MKCOLOUR(0x87878787),
    01279   MKCOLOUR(0x87878787), // height 229
    01280   MKCOLOUR(0x87878787),
    01281
    01282 // TODO: extend untill here
    01283
    01284   /* purple top */
    01285   MKCOLOUR(0x1F27AF27), // height 231
    01286   MKCOLOUR(0x1F27AF27), // height 232
    01287   MKCOLOUR(0x1F274FAF), // height 233
    01288   MKCOLOUR(0x1F274FAF), // height 234
    01289   MKCOLOUR(0x4F274FAF), // height 235
    01290   MKCOLOUR(0x4F274FAF), // height 236
    01291   MKCOLOUR(0x4FAF1FAF), // height 237
    01292   MKCOLOUR(0x4FAF1FAF), // height 238
    01293   MKCOLOUR(0x4F2727AF), // height 239
    01294   MKCOLOUR(0x4F2727AF), // height 240
    01295   MKCOLOUR(0x4F27AF27), // height 241
    01296   MKCOLOUR(0x4F27AF27), // height 242
    01297   MKCOLOUR(0x4F27AFAF), // height 243
    01298   MKCOLOUR(0x4F27AFAF), // height 244
    01299   MKCOLOUR(0x4FAF2727), // height 245
    01300   MKCOLOUR(0x4FAF2727), // height 246
    01301   MKCOLOUR(0x4FAF27AF), // height 247
    01302   MKCOLOUR(0x4FAF27AF), // height 248
    01303   MKCOLOUR(0x4FAFAF27), // height 249
    01304   MKCOLOUR(0x4FAFAF27), // height 250
    01305   MKCOLOUR(0x4FAFAFAF), // height 251
    01306   MKCOLOUR(0x4FAFAFAF), // height 252
    01307   MKCOLOUR(0x4FAFAFCF), // height 253
    01308   MKCOLOUR(0x4FAFAFCF), // height 254
    01309   MKCOLOUR(0x4FAFCFAF), // height 255
    01310   MKCOLOUR(0x4FCFAFAF), /* 1 extra color for people not liking the flood_warning feature. */
    01311   /* Flashing test with current parameters no longer needed. */
    01312   //MKCOLOUR(0x04dcdcdc), /* FLASHING TEST (You can use this when going for 512 colours.) */
    01313 };
    01314 assert_compile(lengthof(_violet_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
    01315
    01319 static const uint32 _stuck_counter_colours[] = {
    01320   MKCOLOUR(0xD0D0D0D0),
    01321   MKCOLOUR(0xCECECECE),
    01322   MKCOLOUR(0xBFBFBFBF),
    01323   MKCOLOUR(0xBDBDBDBD),
    01324   MKCOLOUR(0xBABABABA),
    01325   MKCOLOUR(0xB8B8B8B8),
    01326   MKCOLOUR(0xB6B6B6B6),
    01327   MKCOLOUR(0xB4B4B4B4),
    01328 };
    01329 assert_compile(lengthof(_stuck_counter_colours) == 8);
    01330
    01332 struct SmallMapColourScheme {
    01333   const uint32 *height_colours;
    01334   uint32 default_colour;
    01335 };
    01336
    01338 static const SmallMapColourScheme _heightmap_schemes_old[] = {
    01339   {_green_map_heights_old,      MKCOLOUR_XXXX(0x54)},
    01340   {_dark_green_map_heights_old, MKCOLOUR_XXXX(0x62)},
    01341   {_violet_map_heights_old,     MKCOLOUR_XXXX(0x82)},
    01342 };
    01343
    01345 static const SmallMapColourScheme _heightmap_schemes_extended[] = {
    01346   {_green_map_heights_extended,      MKCOLOUR(0x54545454)},
    01347   {_dark_green_map_heights_extended, MKCOLOUR(0x62626262)},
    01348   {_violet_map_heights_extended,     MKCOLOUR(0x82828282)},
    01349 };
    01350
    01354 void BuildLandLegend()
    01355 {
    01356   if (AllowMoreHeightlevels()) {
    01357     for (LegendAndColour *lc = _legend_land_contours_extended; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
    01358       lc->colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
    01359     }
    01360   } else {
    01361     for (LegendAndColour *lc = _legend_land_contours_old; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
    01362       lc->colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
    01363     }
    01364   }
    01365 }
    01366
    01370 void BuildOwnerLegend()
    01371 {
    01372   if (AllowMoreHeightlevels()) {
    01373     _legend_land_owners[1].colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].default_colour;
    01374   } else {
    01375     _legend_land_owners[1].colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].default_colour;
    01376   }
    01377
    01378   int i = NUM_NO_COMPANY_ENTRIES;
    01379   const Company *c;
    01380   FOR_ALL_COMPANIES(c) {
    01381     _legend_land_owners[i].colour = _colour_gradient[c->colour][5];
    01382     _legend_land_owners[i].company = c->index;
    01383     _legend_land_owners[i].show_on_map = true;
    01384     _legend_land_owners[i].col_break = false;
    01385     _legend_land_owners[i].end = false;
    01386     _company_to_list_pos[c->index] = i;
    01387     i++;
    01388   }
    01389
    01390   /* Terminate the list */
    01391   _legend_land_owners[i].end = true;
    01392
    01393   /* Store maximum amount of owner legend entries. */
    01394   _smallmap_company_count = i;
    01395 }
    01396
    01397 struct AndOr {
    01398   uint32 mor;
    01399   uint32 mand;
    01400 };
    01401
    01402 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
    01403 {
    01404   return (colour & mask->mand) | mask->mor;
    01405 }
    01406
    01408 static const AndOr _smallmap_contours_andor[] = {
    01409   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_CLEAR
    01410   {MKCOLOUR_0XX0(PC_GREY      ), MKCOLOUR_F00F}, // MP_RAILWAY
    01411   {MKCOLOUR_0XX0(PC_BLACK     ), MKCOLOUR_F00F}, // MP_ROAD
    01412   {MKCOLOUR_0XX0(PC_DARK_RED  ), MKCOLOUR_F00F}, // MP_HOUSE
    01413   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_TREES
    01414   {MKCOLOUR_XXXX(PC_LIGHT_BLUE), MKCOLOUR_0000}, // MP_STATION
    01415   {MKCOLOUR_XXXX(PC_WATER     ), MKCOLOUR_0000}, // MP_WATER
    01416   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_VOID
    01417   {MKCOLOUR_XXXX(PC_DARK_RED  ), MKCOLOUR_0000}, // MP_INDUSTRY
    01418   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
    01419   {MKCOLOUR_0XX0(PC_DARK_RED  ), MKCOLOUR_F00F}, // MP_OBJECT
    01420   {MKCOLOUR_0XX0(PC_GREY      ), MKCOLOUR_F00F},
    01421 };
    01422
    01424 static const AndOr _smallmap_vehicles_andor[] = {
    01425   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_CLEAR
    01426   {MKCOLOUR_0XX0(PC_BLACK     ), MKCOLOUR_F00F}, // MP_RAILWAY
    01427   {MKCOLOUR_0XX0(PC_BLACK     ), MKCOLOUR_F00F}, // MP_ROAD
    01428   {MKCOLOUR_0XX0(PC_DARK_RED  ), MKCOLOUR_F00F}, // MP_HOUSE
    01429   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_TREES
    01430   {MKCOLOUR_0XX0(PC_BLACK     ), MKCOLOUR_F00F}, // MP_STATION
    01431   {MKCOLOUR_XXXX(PC_WATER     ), MKCOLOUR_0000}, // MP_WATER
    01432   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_VOID
    01433   {MKCOLOUR_XXXX(PC_DARK_RED  ), MKCOLOUR_0000}, // MP_INDUSTRY
    01434   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
    01435   {MKCOLOUR_0XX0(PC_DARK_RED  ), MKCOLOUR_F00F}, // MP_OBJECT
    01436   {MKCOLOUR_0XX0(PC_BLACK     ), MKCOLOUR_F00F},
    01437 };
    01438
    01440 static const byte _tiletype_importance[] = {
    01441   2, // MP_CLEAR
    01442   8, // MP_RAILWAY
    01443   7, // MP_ROAD
    01444   5, // MP_HOUSE
    01445   2, // MP_TREES
    01446   9, // MP_STATION
    01447   2, // MP_WATER
    01448   1, // MP_VOID
    01449   6, // MP_INDUSTRY
    01450   8, // MP_TUNNELBRIDGE
    01451   2, // MP_OBJECT
    01452   0,
    01453 };
    01454
    01455
    01456 static inline TileType GetEffectiveTileType(TileIndex tile)
    01457 {
    01458   TileType t = GetTileType(tile);
    01459
    01460   if (t == MP_TUNNELBRIDGE) {
    01461     TransportType tt = GetTunnelBridgeTransportType(tile);
    01462
    01463     switch (tt) {
    01464       case TRANSPORT_RAIL: t = MP_RAILWAY; break;
    01465       case TRANSPORT_ROAD: t = MP_ROAD;    break;
    01466       default:             t = MP_WATER;   break;
    01467     }
    01468   }
    01469   return t;
    01470 }
    01471
    01478 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
    01479 {
    01480   uint tile_height = TileHeight(tile);
    01481
    01482   if (_settings_client.gui.smallmap_land_colour == 0) {
    01483     if (AllowMoreHeightlevels()) {
    01484       if(_settings_client.gui.smallmap_flood_warning) {
    01485         return ApplyMask(_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
    01486       } else {
    01487         return ApplyMask(_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
    01488       }
    01489     } else {
    01490       if(_settings_client.gui.smallmap_flood_warning) {
    01491         return ApplyMask(_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
    01492       } else {
    01493         return ApplyMask(_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
    01494       }
    01495     }
    01496   } else if (_settings_client.gui.smallmap_land_colour == 1) {
    01497     if (AllowMoreHeightlevels()) {
    01498       if(_settings_client.gui.smallmap_flood_warning) {
    01499         return ApplyMask(_dark_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
    01500       } else {
    01501         return ApplyMask(_dark_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
    01502       }
    01503     } else {
    01504       if(_settings_client.gui.smallmap_flood_warning) {
    01505         return ApplyMask(_dark_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
    01506       } else {
    01507         return ApplyMask(_dark_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
    01508       }
    01509     }
    01510   } else {
    01511     if (AllowMoreHeightlevels()) {
    01512       if(_settings_client.gui.smallmap_flood_warning) {
    01513         return ApplyMask(_violet_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
    01514       } else {
    01515         return ApplyMask(_violet_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
    01516       }
    01517     } else {
    01518       if(_settings_client.gui.smallmap_flood_warning) {
    01519         return ApplyMask(_violet_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
    01520       } else {
    01521         return ApplyMask(_violet_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
    01522       }
    01523     }
    01524   }
    01525 }
    01526
    01534 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
    01535 {
    01536   if (AllowMoreHeightlevels()) {
    01537     const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
    01538     return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
    01539   } else {
    01540     const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
    01541     return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
    01542   }
    01543 }
    01544
    01552 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
    01553 {
    01554   if (t == MP_INDUSTRY) {
    01555     /* If industry is allowed to be seen, use its colour on the map */
    01556     if (_legend_from_industries[_industry_to_list_pos[Industry::GetByTile(tile)->type]].show_on_map) {
    01557       return GetIndustrySpec(Industry::GetByTile(tile)->type)->map_colour * 0x01010101;
    01558     } else {
    01559       /* Otherwise, return the colour which will make it disappear */
    01560       t = (IsTileOnWater(tile) ? MP_WATER : MP_CLEAR);
    01561     }
    01562   }
    01563
    01564   if (_settings_client.gui.smallmap_land_colour == 0) {
    01565     if (AllowMoreHeightlevels()) {
    01566       if(_settings_client.gui.smallmap_flood_warning) {
    01567         return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
    01568       } else {
    01569         return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
    01570       }
    01571     } else {
    01572       if(_settings_client.gui.smallmap_flood_warning) {
    01573         return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
    01574       } else {
    01575         return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
    01576       }
    01577     }
    01578   } else if (_settings_client.gui.smallmap_land_colour == 1) {
    01579     if (AllowMoreHeightlevels()) {
    01580       if(_settings_client.gui.smallmap_flood_warning) {
    01581         return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
    01582       } else {
    01583         return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
    01584       }
    01585     } else {
    01586       if(_settings_client.gui.smallmap_flood_warning) {
    01587         return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
    01588       } else {
    01589         return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
    01590       }
    01591     }
    01592   } else {
    01593     if (AllowMoreHeightlevels()) {
    01594       if(_settings_client.gui.smallmap_flood_warning) {
    01595         return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
    01596       } else {
    01597         return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
    01598       }
    01599     } else {
    01600       if(_settings_client.gui.smallmap_flood_warning) {
    01601         return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
    01602       } else {
    01603         return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
    01604       }
    01605     }
    01606   }
    01607 }
    01608
    01616 static inline uint32 GetSmallMapStuckRoutesPixels(TileIndex tile, TileType t)
    01617 {
    01618   if (t == MP_STATION) {
    01619     switch (GetStationType(tile)) {
    01620       case STATION_RAIL:    return MKCOLOUR(0x56565656);
    01621       case STATION_AIRPORT: return MKCOLOUR(0xB8B8B8B8);
    01622       case STATION_TRUCK:   return MKCOLOUR(0xC2C2C2C2);
    01623       case STATION_BUS:     return MKCOLOUR(0xBFBFBFBF);
    01624       case STATION_DOCK:    return MKCOLOUR(0x98989898);
    01625       default:              return MKCOLOUR(0xFFFFFFFF);
    01626     }
    01627   } else if (t == MP_RAILWAY) {
    01628     byte c = GetStuckCounter(tile);
    01629     if (c==0) return 0;
    01630     return _stuck_counter_colours[c/32];
    01631   }
    01632
    01633   /* Ground colour */
    01634   if (AllowMoreHeightlevels()) {
    01635     const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
    01636     return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
    01637   } else {
    01638     const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
    01639     return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
    01640   }
    01641 }
    01642
    01650 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
    01651 {
    01652   if (t == MP_STATION) {
    01653     switch (GetStationType(tile)) {
    01654       case STATION_RAIL:    return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
    01655       case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
    01656       case STATION_TRUCK:   return MKCOLOUR_XXXX(PC_ORANGE);
    01657       case STATION_BUS:     return MKCOLOUR_XXXX(PC_YELLOW);
    01658       case STATION_DOCK:    return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
    01659       default:              return MKCOLOUR_FFFF;
    01660     }
    01661   } else if (t == MP_RAILWAY) {
    01662     AndOr andor = {
    01663       MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
    01664       _smallmap_contours_andor[t].mand
    01665     };
    01666
    01667     if (AllowMoreHeightlevels()) {
    01668       const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
    01669       return ApplyMask(cs->default_colour, &andor);
    01670     } else {
    01671       const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
    01672       return ApplyMask(cs->default_colour, &andor);
    01673     }
    01674   }
    01675
    01676   /* Ground colour */
    01677   if (AllowMoreHeightlevels()) {
    01678     const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
    01679     return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
    01680   } else {
    01681     const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
    01682     return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
    01683   }
    01684 }
    01685
    01693 static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
    01694 {
    01695   return _smallmap_show_heightmap ? GetSmallMapContoursPixels(tile, t) : GetSmallMapRoutesPixels(tile, t);
    01696 }
    01697
    01698 static const uint32 _vegetation_clear_bits[] = {
    01699   MKCOLOUR_XXXX(PC_GRASS_LAND),
    01700   MKCOLOUR_XXXX(PC_ROUGH_LAND),
    01701   MKCOLOUR_XXXX(PC_GREY),
    01702   MKCOLOUR_XXXX(PC_FIELDS),
    01703   MKCOLOUR_XXXX(PC_LIGHT_BLUE),
    01704   MKCOLOUR_XXXX(PC_ORANGE),
    01705   MKCOLOUR_XXXX(PC_GRASS_LAND),
    01706   MKCOLOUR_XXXX(PC_GRASS_LAND),
    01707 };
    01708
    01716 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
    01717 {
    01718   switch (t) {
    01719     case MP_CLEAR:
    01720       return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR_XXXX(PC_BARE_LAND) : _vegetation_clear_bits[GetClearGround(tile)];
    01721
    01722     case MP_INDUSTRY:
    01723       return GetIndustrySpec(Industry::GetByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR_XXXX(PC_GREEN) : MKCOLOUR_XXXX(PC_DARK_RED);
    01724
    01725     case MP_TREES:
    01726       if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT || GetTreeGround(tile) == TREE_GROUND_ROUGH_SNOW) {
    01727         return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
    01728       }
    01729       return MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
    01730
    01731     default:
    01732       return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
    01733   }
    01734 }
    01735
    01743 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
    01744 {
    01745   Owner o;
    01746
    01747   switch (t) {
    01748     case MP_INDUSTRY: return MKCOLOUR_XXXX(PC_DARK_GREY);
    01749     case MP_HOUSE:    return MKCOLOUR_XXXX(PC_DARK_RED);
    01750     default:          o = GetTileOwner(tile); break;
    01751     /* FIXME: For MP_ROAD there are multiple owners.
    01752      * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
    01753      * even if there are no ROADTYPE_ROAD bits on the tile.
    01754      */
    01755   }
    01756
    01757   if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
    01758     if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
    01759     if (AllowMoreHeightlevels()) {
    01760       const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
    01761       if(_settings_client.gui.smallmap_flood_warning) {
    01762         return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
    01763       } else {
    01764         return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
    01765
    01766       }
    01767     } else {
    01768       const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
    01769       if(_settings_client.gui.smallmap_flood_warning) {
    01770         return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
    01771       } else {
    01772         return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
    01773       }
    01774     }
    01775   } else if (o == OWNER_TOWN) {
    01776     return MKCOLOUR_XXXX(PC_DARK_RED);
    01777   }
    01778
    01779   return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
    01780 }
    01781
    01782 static Point TileCoordFromScreenCoord(int x, int y)
    01783 {
    01784   /*  What we calculate here is the inverse function of RemapCoords,
    01785    *  assuming z = 0 in RemapCoords.
    01786    */
    01787   Point pt;
    01788   pt.x = (2 * y - x) / 4;
    01789   pt.y = (x + 2 * y) / 4;
    01790   return pt;
    01791 }
    01792
    01794 static const byte _vehicle_type_colours[6] = {
    01795   PC_RED, PC_YELLOW, PC_LIGHT_BLUE, PC_WHITE, PC_BLACK, PC_RED
    01796 };
    01797
    01806 void DrawVertex(int x, int y, int size, int colour, int border_colour)
    01807 {
    01808   size--;
    01809   int w1 = size / 2;
    01810   int w2 = size / 2 + size % 2;
    01811
    01812   GfxFillRect(x - w1, y - w1, x + w2, y + w2, colour);
    01813
    01814   w1++;
    01815   w2++;
    01816   GfxDrawLine(x - w1, y - w1, x + w2, y - w1, border_colour);
    01817   GfxDrawLine(x - w1, y + w2, x + w2, y + w2, border_colour);
    01818   GfxDrawLine(x - w1, y - w1, x - w1, y + w2, border_colour);
    01819   GfxDrawLine(x + w2, y - w1, x + w2, y + w2, border_colour);
    01820 }
    01821
    01823 class SmallMapWindow : public Window {
    01825   enum SmallMapType {
    01826     SMT_CONTOUR,
    01827     SMT_VEHICLES,
    01828     SMT_INDUSTRY,
    01829     SMT_LINKSTATS,
    01830     SMT_ROUTES,
    01831     SMT_VEGETATION,
    01832     SMT_OWNER,
    01833   };
    01834
    01842   struct VehicleAndPosition {
    01843     VehicleAndPosition(const Vehicle *v) : vehicle(v->index)
    01844     {
    01845       this->position.x = v->x_pos;
    01846       this->position.y = v->y_pos;
    01847     }
    01848
    01849     Point position;
    01850     VehicleID vehicle;
    01851   };
    01852
    01853   typedef std::list<VehicleAndPosition> VehicleList;
    01854   VehicleList vehicles_on_map;
    01855
    01857   enum ZoomLevelChange {
    01858     ZLC_INITIALIZE,
    01859     ZLC_ZOOM_OUT,
    01860     ZLC_ZOOM_IN,
    01861   };
    01862
    01863   static SmallMapType map_type;
    01864   static bool show_towns;
    01865
    01866   static const uint LEGEND_BLOB_WIDTH = 8;
    01867   static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2;
    01868   uint min_number_of_fixed_rows;
    01869   uint column_width;
    01870
    01871   bool HasButtons()
    01872   {
    01873     return this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER;
    01874   }
    01875
    01876   Point cursor;
    01877
    01878   struct BaseCargoDetail {
    01879     BaseCargoDetail()
    01880     {
    01881       this->Clear();
    01882     }
    01883
    01884     void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow)
    01885     {
    01886       this->capacity += orig_link.Capacity();
    01887       this->usage += orig_link.Usage();
    01888       this->planned += orig_flow.Planned();
    01889       this->sent += orig_flow.Sent();
    01890     }
    01891
    01892     void Clear()
    01893     {
    01894       this->capacity = this->usage = this->planned = this->sent = 0;
    01895     }
    01896
    01897     uint capacity;
    01898     uint usage;
    01899     uint planned;
    01900     uint sent;
    01901   };
    01902
    01903   struct CargoDetail : public BaseCargoDetail {
    01904     CargoDetail(const LegendAndColour * c, const LinkStat &ls, const FlowStat &fs) : legend(c)
    01905     {
    01906       this->AddLink(ls, fs);
    01907     }
    01908
    01909     const LegendAndColour *legend;
    01910   };
    01911
    01912   typedef std::vector<CargoDetail> StatVector;
    01913
    01914   struct LinkDetails {
    01915     LinkDetails() {this->Clear();}
    01916
    01917     StationID sta;
    01918     StationID stb;
    01919     StatVector a_to_b;
    01920     StatVector b_to_a;
    01921
    01922     void Clear()
    01923     {
    01924       this->sta = INVALID_STATION;
    01925       this->stb = INVALID_STATION;
    01926       this->a_to_b.clear();
    01927       this->b_to_a.clear();
    01928     }
    01929
    01930     bool Empty() const
    01931     {
    01932       return this->sta == INVALID_STATION;
    01933     }
    01934   };
    01935
    01940   mutable LinkDetails link_details;
    01941   mutable StationID supply_details;
    01942
    01943   int32 scroll_x;
    01944   int32 scroll_y;
    01945   int32 subscroll;
    01946   int zoom;
    01947
    01948   static const uint8 FORCE_REFRESH_PERIOD = 0x1F;
    01949   static const uint8 REFRESH_NEXT_TICK = 1;
    01950   uint8 refresh;
    01951
    01958   FORCEINLINE Point RemapTile(int tile_x, int tile_y) const
    01959   {
    01960     if (this->zoom > 0) {
    01961       int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
    01962       int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
    01963
    01964       /* For negative offsets, round towards -inf. */
    01965       if (x_offset < 0) x_offset -= this->zoom - 1;
    01966       if (y_offset < 0) y_offset -= this->zoom - 1;
    01967
    01968       return RemapCoords(x_offset / this->zoom, y_offset / this->zoom, 0);
    01969     } else {
    01970       int x_offset = tile_x * (-this->zoom) - this->scroll_x * (-this->zoom) / (int)TILE_SIZE;
    01971       int y_offset = tile_y * (-this->zoom) - this->scroll_y * (-this->zoom) / (int)TILE_SIZE;
    01972
    01973       return RemapCoords(x_offset, y_offset, 0);
    01974     }
    01975   }
    01976
    01987   FORCEINLINE Point PixelToWorld(int px, int py, int *sub, bool add_sub = true) const
    01988   {
    01989     if (add_sub) px += this->subscroll;  // Total horizontal offset.
    01990
    01991     /* For each two rows down, add a x and a y tile, and
    01992      * For each four pixels to the right, move a tile to the right. */
    01993     Point pt = {
    01994       ((py >> 1) - (px >> 2)) * TILE_SIZE,
    01995       ((py >> 1) + (px >> 2)) * TILE_SIZE
    01996     };
    01997
    01998     if (this->zoom > 0) {
    01999       pt.x *= this->zoom;
    02000       pt.y *= this->zoom;
    02001     } else {
    02002       pt.x /= (-this->zoom);
    02003       pt.y /= (-this->zoom);
    02004     }
    02005
    02006     px &= 3;
    02007
    02008     if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
    02009       int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
    02010       if (px < 2) {
    02011         pt.x += offset;
    02012         px += 2;
    02013       } else {
    02014         pt.y += offset;
    02015         px -= 2;
    02016       }
    02017     }
    02018
    02019     *sub = px;
    02020     return pt;
    02021   }
    02022
    02032   Point ComputeScroll(int tx, int ty, int x, int y, int *sub)
    02033   {
    02034     assert(x >= 0 && y >= 0);
    02035
    02036     int new_sub;
    02037     Point tile_xy = PixelToWorld(x, y, &new_sub, false);
    02038     tx -= tile_xy.x;
    02039     ty -= tile_xy.y;
    02040
    02041     int offset = this->zoom < 0 ? TILE_SIZE / (-this->zoom) : this->zoom * TILE_SIZE;
    02042
    02043     Point scroll;
    02044     if (new_sub == 0) {
    02045       *sub = 0;
    02046       scroll.x = tx + offset;
    02047       scroll.y = ty - offset;
    02048     } else {
    02049       *sub = 4 - new_sub;
    02050       scroll.x = tx + 2 * offset;
    02051       scroll.y = ty - 2 * offset;
    02052     }
    02053     return scroll;
    02054   }
    02055
    02062   void SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
    02063   {
    02064     static const int zoomlevels[] = {-4, -2, 1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
    02065     static const int MIN_ZOOM_INDEX = 0;
    02066     static const int DEFAULT_ZOOM_INDEX = 2;
    02067     static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
    02068
    02069     int new_index, cur_index, sub;
    02070     Point position;
    02071     switch (change) {
    02072       case ZLC_INITIALIZE:
    02073         cur_index = - 1; // Definitely different from new_index.
    02074         new_index = DEFAULT_ZOOM_INDEX;
    02075         break;
    02076
    02077       case ZLC_ZOOM_IN:
    02078       case ZLC_ZOOM_OUT:
    02079         for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
    02080           if (this->zoom == zoomlevels[cur_index]) break;
    02081         }
    02082         assert(cur_index <= MAX_ZOOM_INDEX);
    02083
    02084         position = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
    02085         new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
    02086         break;
    02087
    02088       default: NOT_REACHED();
    02089     }
    02090
    02091     if (new_index != cur_index) {
    02092       this->zoom = zoomlevels[new_index];
    02093       if (cur_index >= 0) {
    02094         Point new_pos = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
    02095         this->SetNewScroll(this->scroll_x + position.x - new_pos.x,
    02096             this->scroll_y + position.y - new_pos.y, sub);
    02097       }
    02098       this->SetWidgetDisabledState(SM_WIDGET_ZOOM_IN,  this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
    02099       this->SetWidgetDisabledState(SM_WIDGET_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
    02100       this->SetDirty();
    02101     }
    02102   }
    02103
    02109   inline uint32 GetTileColours(const TileArea &ta) const
    02110   {
    02111     int importance = 0;
    02112     TileIndex tile = INVALID_TILE; // Position of the most important tile.
    02113     TileType et = MP_VOID;         // Effective tile type at that position.
    02114
    02115     TILE_AREA_LOOP(ti, ta) {
    02116       TileType ttype = GetEffectiveTileType(ti);
    02117       if (_tiletype_importance[ttype] > importance) {
    02118         importance = _tiletype_importance[ttype];
    02119         tile = ti;
    02120         et = ttype;
    02121       }
    02122     }
    02123
    02124     switch (this->map_type) {
    02125       case SMT_CONTOUR:
    02126         return GetSmallMapContoursPixels(tile, et);
    02127
    02128       case SMT_VEHICLES:
    02129         return GetSmallMapVehiclesPixels(tile, et);
    02130
    02131       case SMT_INDUSTRY:
    02132         return GetSmallMapIndustriesPixels(tile, et);
    02133
    02134       case SMT_ROUTES:
    02135         return GetSmallMapStuckRoutesPixels(tile, et);
    02136
    02137       case SMT_VEGETATION:
    02138         return GetSmallMapVegetationPixels(tile, et);
    02139
    02140       case SMT_OWNER:
    02141         return GetSmallMapOwnerPixels(tile, et);
    02142
    02143       case SMT_LINKSTATS:
    02144         return GetSmallMapLinkStatsPixels(tile, et);
    02145
    02146       default: NOT_REACHED();
    02147     }
    02148   }
    02149
    02164   void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
    02165   {
    02166     void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
    02167     uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
    02168
    02169     int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
    02170     int extent = this->zoom > 0 ? this->zoom : 1;
    02171
    02172     do {
    02173       /* Check if the tile (xc,yc) is within the map range */
    02174       if (xc / TILE_SIZE >= MapMaxX() || yc / TILE_SIZE >= MapMaxY()) continue;
    02175
    02176       /* Check if the dst pointer points to a pixel inside the screen buffer */
    02177       if (dst < _screen.dst_ptr) continue;
    02178       if (dst >= dst_ptr_abs_end) continue;
    02179
    02180       /* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
    02181       TileArea ta;
    02182       if (min_xy == 1 && (xc < TILE_SIZE || yc < TILE_SIZE)) {
    02183         if (this->zoom <= 1) continue; // The tile area is empty, don't draw anything.
    02184
    02185         ta = TileArea(TileXY(max(min_xy, xc / TILE_SIZE), max(min_xy, yc / TILE_SIZE)), this->zoom - (xc < TILE_SIZE), this->zoom - (yc < TILE_SIZE));
    02186       } else {
    02187         ta = TileArea(TileXY(xc / TILE_SIZE, yc / TILE_SIZE), extent, extent);
    02188       }
    02189       ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
    02190
    02191       uint32 val = this->GetTileColours(ta);
    02192       uint8 *val8 = (uint8 *)&val;
    02193       int idx = max(0, -start_pos);
    02194       for (int pos = max(0, start_pos); pos < end_pos; pos++) {
    02195         blitter->SetPixel(dst, idx, 0, val8[idx]);
    02196         idx++;
    02197       }
    02198     /* Switch to next tile in the column */
    02199     } while (xc += increment, yc += increment, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
    02200   }
    02201
    02207   void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
    02208   {
    02209     for(VehicleList::const_iterator i = this->vehicles_on_map.begin(); i != this->vehicles_on_map.end(); ++i) {
    02210       const Vehicle *v = Vehicle::GetIfValid(i->vehicle);
    02211       if (v == NULL) continue;
    02212
    02213       /* Remap into flat coordinates. */
    02214       Point pt = RemapTile(i->position.x / (int)TILE_SIZE, i->position.y / (int)TILE_SIZE);
    02215
    02216       int y = pt.y - dpi->top;
    02217       int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
    02218
    02219       int scale = this->zoom < 0 ? -this->zoom : 1;
    02220
    02221       /* Calculate pointer to pixel and the colour */
    02222       byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
    02223
    02224       /* Draw rhombus */
    02225       for (int dy = 0; dy < scale; dy++) {
    02226         for (int dx = 0; dx < scale; dx++) {
    02227           Point pt = RemapCoords(dx, dy, 0);
    02228           if (IsInsideMM(y + pt.y, 0, dpi->height)) {
    02229             if (IsInsideMM(x + pt.x, 0, dpi->width)) {
    02230               blitter->SetPixel(dpi->dst_ptr, x + pt.x, y + pt.y, colour);
    02231             }
    02232             if (IsInsideMM(x + pt.x + 1, 0, dpi->width)) {
    02233               blitter->SetPixel(dpi->dst_ptr, x + pt.x + 1, y + pt.y, colour);
    02234             }
    02235           }
    02236         }
    02237       }
    02238     }
    02239   }
    02240
    02241   FORCEINLINE Point GetStationMiddle(const Station *st) const
    02242   {
    02243     int x = (st->rect.right + st->rect.left + 1) / 2;
    02244     int y = (st->rect.bottom + st->rect.top + 1) / 2;
    02245     Point ret = this->RemapTile(x, y);
    02246     ret.x -= 3 + this->subscroll;
    02247     if (this->zoom < 0) {
    02248       /* add half a tile if width or height is odd */
    02249       if (((st->rect.bottom - st->rect.top) & 1) == 0) {
    02250         Point offset = RemapCoords(0, -this->zoom / 2, 0);
    02251         ret.x += offset.x;
    02252         ret.y += offset.y;
    02253       }
    02254       if (((st->rect.right - st->rect.left) & 1) == 0) {
    02255         Point offset = RemapCoords(-this->zoom / 2, 0, 0);
    02256         ret.x += offset.x;
    02257         ret.y += offset.y;
    02258       }
    02259     }
    02260     return ret;
    02261   }
    02262
    02263   StationID DrawStationDots() const
    02264   {
    02265     const Station *supply_details = NULL;
    02266
    02267     const Station *st;
    02268     FOR_ALL_STATIONS(st) {
    02269       if (((st->owner != _local_company && Company::IsValidID(st->owner)) ||
    02270           st->rect.IsEmpty()) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
    02271
    02272       Point pt = GetStationMiddle(st);
    02273
    02274       if (supply_details == NULL && CheckStationSelected(&pt)) {
    02275         supply_details = st;
    02276       }
    02277
    02278       /* Add up cargo supplied for each selected cargo type */
    02279       uint q = 0;
    02280       int colour = 0;
    02281       int numCargos = 0;
    02282
    02283       if (AllowMoreHeightlevels()) {
    02284         for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02285           const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
    02286           if (!tbl.show_on_map && supply_details != st) continue;
    02287           uint supply = st->goods[tbl.type].supply;
    02288           if (supply > 0) {
    02289             q += supply;
    02290             colour += tbl.colour;
    02291             numCargos++;
    02292           }
    02293         }
    02294
    02295       } else {
    02296         for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02297           const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
    02298           if (!tbl.show_on_map && supply_details != st) continue;
    02299           uint supply = st->goods[tbl.type].supply;
    02300           if (supply > 0) {
    02301             q += supply;
    02302             colour += tbl.colour;
    02303             numCargos++;
    02304           }
    02305         }
    02306       }
    02307
    02308       if (numCargos > 1) colour /= numCargos;
    02309
    02310       uint r = 2;
    02311       if (q >= 10) r++;
    02312       if (q >= 20) r++;
    02313       if (q >= 40) r++;
    02314       if (q >= 80) r++;
    02315       if (q >= 160) r++;
    02316
    02317       DrawVertex(pt.x, pt.y, r, colour, _colour_gradient[COLOUR_GREY][supply_details == st ? 3 : 1]);
    02318     }
    02319     return (supply_details == NULL) ? INVALID_STATION : supply_details->index;
    02320   }
    02321
    02322   class LinkDrawer {
    02323
    02324   protected:
    02325     virtual void DrawContent() = 0;
    02326     virtual void Highlight() {}
    02327     virtual void AddLink(const LinkStat &orig_link, const FlowStat &orig_flow, const LegendAndColour &cargo_entry) = 0;
    02328
    02329     FORCEINLINE bool IsLinkVisible()
    02330     {
    02331       const NWidgetBase *wi = this->window->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
    02332       return !((this->pta.x < 0 && this->ptb.x < 0) ||
    02333           (this->pta.y < 0 && this->ptb.y < 0) ||
    02334           (this->pta.x > (int)wi->current_x && this->ptb.x > (int)wi->current_x) ||
    02335           (this->pta.y > (int)wi->current_y && this->ptb.y > (int)wi->current_y));
    02336     }
    02337
    02338     Point pta, ptb;
    02339     bool search_link_details;
    02340     LinkDetails link_details;
    02341     const SmallMapWindow *window;
    02342
    02343     void DrawLink(StationID sta, StationID stb)
    02344     {
    02345       bool highlight_empty = this->search_link_details && this->link_details.Empty();
    02346       bool highlight =
    02347           (sta == this->link_details.sta && stb == this->link_details.stb) ||
    02348           (highlight_empty && window->CheckLinkSelected(&this->pta, &this->ptb));
    02349       bool reverse_empty = this->link_details.b_to_a.empty();
    02350       bool reverse_highlight = (sta == this->link_details.stb && stb == this->link_details.sta);
    02351       if (highlight_empty && highlight) {
    02352         this->link_details.sta = sta;
    02353         this->link_details.stb = stb;
    02354       }
    02355
    02356       if (highlight || reverse_highlight) {
    02357         this->Highlight();
    02358       }
    02359
    02360       if (AllowMoreHeightlevels()) {
    02361         for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02362           const LegendAndColour &cargo_entry = _legend_table_extended[window->map_type][i];
    02363           CargoID cargo = cargo_entry.type;
    02364           if (cargo_entry.show_on_map || highlight || reverse_highlight) {
    02365             GoodsEntry &ge = Station::Get(sta)->goods[cargo];
    02366             FlowStat sum_flows = ge.GetSumFlowVia(stb);
    02367             const LinkStatMap &ls_map = ge.link_stats;
    02368             LinkStatMap::const_iterator i = ls_map.find(stb);
    02369             if (i != ls_map.end()) {
    02370               const LinkStat &link_stat = i->second;
    02371               this->AddLink(link_stat, sum_flows, cargo_entry);
    02372               if (highlight_empty && highlight) {
    02373                 this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
    02374               } else if (reverse_empty && reverse_highlight) {
    02375                 this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
    02376               }
    02377             }
    02378           }
    02379         }
    02380
    02381       } else {
    02382         for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02383           const LegendAndColour &cargo_entry = _legend_table_old[window->map_type][i];
    02384           CargoID cargo = cargo_entry.type;
    02385           if (cargo_entry.show_on_map || highlight || reverse_highlight) {
    02386             GoodsEntry &ge = Station::Get(sta)->goods[cargo];
    02387             FlowStat sum_flows = ge.GetSumFlowVia(stb);
    02388             const LinkStatMap &ls_map = ge.link_stats;
    02389             LinkStatMap::const_iterator i = ls_map.find(stb);
    02390             if (i != ls_map.end()) {
    02391               const LinkStat &link_stat = i->second;
    02392               this->AddLink(link_stat, sum_flows, cargo_entry);
    02393               if (highlight_empty && highlight) {
    02394                 this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
    02395               } else if (reverse_empty && reverse_highlight) {
    02396                 this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
    02397               }
    02398             }
    02399           }
    02400         }
    02401       }
    02402     }
    02403
    02404     virtual void DrawForwBackLinks(StationID sta, StationID stb)
    02405     {
    02406       this->DrawLink(sta, stb);
    02407       this->DrawContent();
    02408       Swap(this->pta, this->ptb);
    02409       this->DrawLink(stb, sta);
    02410       this->DrawContent();
    02411     }
    02412
    02413   public:
    02414     virtual ~LinkDrawer() {}
    02415
    02416     LinkDetails DrawLinks(const SmallMapWindow * w, bool search)
    02417     {
    02418       this->link_details.Clear();
    02419       this->window = w;
    02420       this->search_link_details = search;
    02421       std::set<StationID> seen_stations;
    02422       std::set<std::pair<StationID, StationID> > seen_links;
    02423
    02424       const Station *sta;
    02425       if (AllowMoreHeightlevels()) {
    02426         FOR_ALL_STATIONS(sta) {
    02427           if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
    02428
    02429           for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02430             const LegendAndColour &tbl = _legend_table_extended[window->map_type][i];
    02431             if (!tbl.show_on_map) continue;
    02432
    02433             CargoID c = tbl.type;
    02434             const LinkStatMap &links = sta->goods[c].link_stats;
    02435             for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
    02436               StationID from = sta->index;
    02437               StationID to = i->first;
    02438               if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
    02439                 const Station *stb = Station::Get(to);
    02440
    02441                 if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
    02442                 if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
    02443                 if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
    02444
    02445                 this->pta = this->window->GetStationMiddle(sta);
    02446                 this->ptb = this->window->GetStationMiddle(stb);
    02447                 if (!this->IsLinkVisible()) continue;
    02448
    02449                 this->DrawForwBackLinks(sta->index, stb->index);
    02450                 seen_stations.insert(to);
    02451               }
    02452               seen_links.insert(std::make_pair(from, to));
    02453             }
    02454           }
    02455           seen_stations.clear();
    02456         }
    02457
    02458       } else {
    02459         FOR_ALL_STATIONS(sta) {
    02460           if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
    02461
    02462           for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02463             const LegendAndColour &tbl = _legend_table_old[window->map_type][i];
    02464             if (!tbl.show_on_map) continue;
    02465
    02466             CargoID c = tbl.type;
    02467             const LinkStatMap &links = sta->goods[c].link_stats;
    02468             for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
    02469               StationID from = sta->index;
    02470               StationID to = i->first;
    02471               if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
    02472                 const Station *stb = Station::Get(to);
    02473
    02474                 if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue; // test show all companies links
    02475                 if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
    02476                 if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
    02477
    02478                 this->pta = this->window->GetStationMiddle(sta);
    02479                 this->ptb = this->window->GetStationMiddle(stb);
    02480                 if (!this->IsLinkVisible()) continue;
    02481
    02482                 this->DrawForwBackLinks(sta->index, stb->index);
    02483                 seen_stations.insert(to);
    02484               }
    02485               seen_links.insert(std::make_pair(from, to));
    02486             }
    02487           }
    02488
    02489           seen_stations.clear();
    02490         }
    02491       }
    02492       return this->link_details;
    02493     }
    02494
    02495   };
    02496
    02497   class LinkLineDrawer : public LinkDrawer {
    02498   public:
    02499     LinkLineDrawer() : highlight(false) {}
    02500
    02501   protected:
    02502     typedef std::set<uint16> ColourSet;
    02503     ColourSet colours;
    02504     bool highlight;
    02505
    02506     virtual void DrawForwBackLinks(StationID sta, StationID stb)
    02507     {
    02508       this->DrawLink(sta, stb);
    02509       this->DrawLink(stb, sta);
    02510       this->DrawContent();
    02511     }
    02512
    02513     virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
    02514     {
    02515       this->colours.insert(cargo_entry.colour);
    02516     }
    02517
    02518     virtual void Highlight()
    02519     {
    02520       this->highlight = true;
    02521     }
    02522
    02523     virtual void DrawContent()
    02524     {
    02525       uint colour = 0;
    02526       uint num_colours = 0;
    02527       for (ColourSet::iterator i = colours.begin(); i != colours.end(); ++i) {
    02528         colour += *i;
    02529         num_colours++;
    02530       }
    02531       colour /= num_colours;
    02532       byte border_colour = _colour_gradient[COLOUR_GREY][highlight ? 3 : 1];
    02533       GfxDrawLine(this->pta.x - 1, this->pta.y, this->ptb.x - 1, this->ptb.y, border_colour);
    02534       GfxDrawLine(this->pta.x + 1, this->pta.y, this->ptb.x + 1, this->ptb.y, border_colour);
    02535       GfxDrawLine(this->pta.x, this->pta.y - 1, this->ptb.x, this->ptb.y - 1, border_colour);
    02536       GfxDrawLine(this->pta.x, this->pta.y + 1, this->ptb.x, this->ptb.y + 1, border_colour);
    02537       GfxDrawLine(this->pta.x, this->pta.y, this->ptb.x, this->ptb.y, colour);
    02538       this->colours.clear();
    02539       this->highlight = false;
    02540     }
    02541   };
    02542
    02543   class LinkValueDrawer : public LinkDrawer, public BaseCargoDetail {
    02544   protected:
    02545
    02546     virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
    02547     {
    02548       this->BaseCargoDetail::AddLink(orig_link, orig_flow);
    02549     }
    02550   };
    02551
    02552   class LinkTextDrawer : public LinkValueDrawer {
    02553   protected:
    02554     virtual void DrawContent()
    02555     {
    02556       Point ptm;
    02557       ptm.x = (this->pta.x + 2*this->ptb.x) / 3;
    02558       ptm.y = (this->pta.y + 2*this->ptb.y) / 3;
    02559       int nums = 0;
    02560       if (_legend_linkstats[_smallmap_cargo_count + STAT_CAPACITY].show_on_map) {
    02561         SetDParam(nums++, this->capacity);
    02562       }
    02563       if (_legend_linkstats[_smallmap_cargo_count + STAT_USAGE].show_on_map) {
    02564         SetDParam(nums++, this->usage);
    02565       }
    02566       if (_legend_linkstats[_smallmap_cargo_count + STAT_PLANNED].show_on_map) {
    02567         SetDParam(nums++, this->planned);
    02568       }
    02569       if (_legend_linkstats[_smallmap_cargo_count + STAT_SENT].show_on_map) {
    02570         SetDParam(nums++, this->sent);
    02571       }
    02572       StringID str;
    02573       switch (nums) {
    02574       case 0:
    02575         str = STR_EMPTY; break;
    02576       case 1:
    02577         str = STR_NUM; break;
    02578       case 2:
    02579         str = STR_NUM_RELATION_2; break;
    02580       case 3:
    02581         str = STR_NUM_RELATION_3; break;
    02582       case 4:
    02583         str = STR_NUM_RELATION_4; break;
    02584       default:
    02585         NOT_REACHED();
    02586       }
    02587       DrawString(ptm.x, ptm.x + this->window->ColumnWidth(), ptm.y, str, TC_WHITE);
    02588       this->Clear();
    02589     }
    02590   };
    02591
    02592   class LinkGraphDrawer : public LinkValueDrawer {
    02593     typedef std::multimap<uint, byte, std::greater<uint> > SizeMap;
    02594   protected:
    02595     virtual void DrawContent()
    02596     {
    02597       Point ptm;
    02598       SizeMap sizes;
    02599       /* these floats only serve to calculate the size of the coloured boxes for capacity, usage, planned, sent
    02600        * they are not reused anywhere, so it's network safe.
    02601        */
    02602       const LegendAndColour *legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_USAGE;
    02603       if (legend_entry->show_on_map && this->usage > 0) {
    02604         sizes.insert(std::make_pair((uint)sqrt((float)this->usage), legend_entry->colour));
    02605       }
    02606       legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_CAPACITY;
    02607       if (legend_entry->show_on_map && this->capacity > 0) {
    02608         sizes.insert(std::make_pair((uint)sqrt((float)this->capacity), legend_entry->colour));
    02609       }
    02610       legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_PLANNED;
    02611       if (legend_entry->show_on_map && this->planned > 0) {
    02612         sizes.insert(std::make_pair((uint)sqrt((float)this->planned),  legend_entry->colour));
    02613       }
    02614       legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_SENT;
    02615       if (legend_entry->show_on_map && this->sent > 0) {
    02616         sizes.insert(std::make_pair((uint)sqrt((float)this->sent), legend_entry->colour));
    02617       }
    02618
    02619       ptm.x = (this->pta.x + this->ptb.x) / 2;
    02620       ptm.y = (this->pta.y + this->ptb.y) / 2;
    02621
    02622       for (SizeMap::iterator i = sizes.begin(); i != sizes.end(); ++i) {
    02623         if (this->pta.x > this->ptb.x) {
    02624           ptm.x -= 1;
    02625           GfxFillRect(ptm.x - i->first / 2, ptm.y - i->first * 2, ptm.x, ptm.y, i->second);
    02626         } else {
    02627           ptm.x += 1;
    02628           GfxFillRect(ptm.x, ptm.y - i->first * 2, ptm.x + i->first / 2, ptm.y, i->second);
    02629         }
    02630       }
    02631       this->Clear();
    02632     }
    02633   };
    02634
    02635   static const uint MORE_SPACE_NEEDED = 0x1000;
    02636
    02637   uint DrawLinkDetails(StatVector &details, uint x, uint y, uint right, uint bottom) const
    02638   {
    02639     uint x_orig = x;
    02640     SetDParam(0, 9999);
    02641     static uint entry_width = LEGEND_BLOB_WIDTH +
    02642         GetStringBoundingBox(STR_ABBREV_PASSENGERS).width +
    02643         GetStringBoundingBox(STR_SMALLMAP_LINK_CAPACITY).width +
    02644         GetStringBoundingBox(STR_SMALLMAP_LINK_USAGE).width +
    02645         GetStringBoundingBox(STR_SMALLMAP_LINK_PLANNED).width +
    02646         GetStringBoundingBox(STR_SMALLMAP_LINK_SENT).width;
    02647     uint entries_per_row = (right - x_orig) / entry_width;
    02648     if (details.empty()) {
    02649       DrawString(x, x + entry_width, y, STR_TINY_NOTHING, TC_BLACK);
    02650       return y + FONT_HEIGHT_SMALL;
    02651     }
    02652     for (uint i = 0; i < details.size(); ++i) {
    02653       CargoDetail &detail = details[i];
    02654       if (x + entry_width >= right) {
    02655         x = x_orig;
    02656         y += FONT_HEIGHT_SMALL;
    02657         if (y + 2 * FONT_HEIGHT_SMALL > bottom && details.size() - i > entries_per_row) {
    02658           return y | MORE_SPACE_NEEDED;
    02659         }
    02660       }
    02661       uint x_next = x + entry_width;
    02662       if (detail.legend->show_on_map) {
    02663         GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
    02664       }
    02665       GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, detail.legend->colour); // legend colour
    02666       x += LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
    02667       TextColour textcol[4];
    02668       for (int stat = STAT_CAPACITY; stat <= STAT_SENT; ++stat) {
    02669         textcol[stat] = (detail.legend->show_on_map && _legend_linkstats[_smallmap_cargo_count + stat].show_on_map) ?
    02670             TC_BLACK : TC_GREY;
    02671       }
    02672
    02673       SetDParam(0, CargoSpec::Get(detail.legend->type)->abbrev);
    02674       x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK, detail.legend->show_on_map ? TC_BLACK : TC_GREY);
    02675       SetDParam(0, detail.capacity);
    02676       x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_CAPACITY, textcol[STAT_CAPACITY]);
    02677       SetDParam(0, detail.usage);
    02678       x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_USAGE, textcol[STAT_USAGE]);
    02679       SetDParam(0, detail.planned);
    02680       x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_PLANNED, textcol[STAT_PLANNED]);
    02681       SetDParam(0, detail.sent);
    02682       x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_SENT, textcol[STAT_SENT]);
    02683       x = x_next;
    02684     }
    02685     return y + FONT_HEIGHT_SMALL;
    02686   }
    02687
    02688   uint DrawLinkDetailCaption(uint x, uint y, uint right, StationID sta, StationID stb) const
    02689   {
    02690     SetDParam(0, sta);
    02691     SetDParam(1, stb);
    02692     static uint height = GetStringBoundingBox(STR_SMALLMAP_LINK_CAPTION).height;
    02693     DrawString(x, right - 1, y, STR_SMALLMAP_LINK_CAPTION, TC_BLACK);
    02694     y += height;
    02695     return y;
    02696   }
    02697
    02698   void DrawLinkDetails(uint x, uint y, uint right, uint bottom) const
    02699   {
    02700     y = DrawLinkDetailCaption(x, y, right, this->link_details.sta, this->link_details.stb);
    02701     if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
    02702       DrawString(x, right, y, "...", TC_BLACK);
    02703       return;
    02704     }
    02705     y = DrawLinkDetails(this->link_details.a_to_b, x, y, right, bottom);
    02706     if (y + 3 * FONT_HEIGHT_SMALL > bottom) {
    02707       /* caption takes more space -> 3 * row height */
    02708       DrawString(x, right, y, "...", TC_BLACK);
    02709       return;
    02710     }
    02711     y = DrawLinkDetailCaption(x, y + 2, right, this->link_details.stb, this->link_details.sta);
    02712     if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
    02713       DrawString(x, right, y, "...", TC_BLACK);
    02714       return;
    02715     }
    02716     y = DrawLinkDetails(this->link_details.b_to_a, x, y, right, bottom);
    02717     if (y & MORE_SPACE_NEEDED) {
    02718       /* only draw "..." if more entries would have been drawn */
    02719       DrawString(x, right, y ^ MORE_SPACE_NEEDED, "...", TC_BLACK);
    02720       return;
    02721     }
    02722   }
    02723
    02724   void DrawSupplyDetails(uint x, uint y_org, uint bottom) const
    02725   {
    02726     const Station *st = Station::GetIfValid(this->supply_details);
    02727     if (st == NULL) return;
    02728     SetDParam(0, this->supply_details);
    02729     static uint height = GetStringBoundingBox(STR_SMALLMAP_SUPPLY_CAPTION).height;
    02730     DrawString(x, x + 2 * this->column_width - 1, y_org, STR_SMALLMAP_SUPPLY_CAPTION, TC_BLACK);
    02731     y_org += height;
    02732     uint y = y_org;
    02733     if (AllowMoreHeightlevels()) {
    02734       for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02735         if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
    02736           /* Column break needed, continue at top, SD_LEGEND_COLUMN_WIDTH pixels
    02737            * (one "row") to the right. */
    02738           x += this->column_width;
    02739           y = y_org;
    02740         }
    02741
    02742         const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
    02743
    02744         CargoID c = tbl.type;
    02745         uint supply = st->goods[c].supply;
    02746         if (supply > 0) {
    02747           TextColour textcol = TC_BLACK;
    02748           if (tbl.show_on_map) {
    02749             GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
    02750           } else {
    02751             textcol = TC_GREY;
    02752           }
    02753           SetDParam(0, c);
    02754           SetDParam(1, supply);
    02755           DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
    02756           GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour); // legend colour
    02757           y += FONT_HEIGHT_SMALL;
    02758         }
    02759       }
    02760
    02761     } else {
    02762       for (int i = 0; i < _smallmap_cargo_count; ++i) {
    02763         if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
    02764           /* Column break needed, continue at top, SD_LEGEND_COLUMN_WIDTH pixels
    02765            * (one "row") to the right. */
    02766           x += this->column_width;
    02767           y = y_org;
    02768         }
    02769
    02770         const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
    02771
    02772         CargoID c = tbl.type;
    02773         uint supply = st->goods[c].supply;
    02774         if (supply > 0) {
    02775           TextColour textcol = TC_BLACK;
    02776           if (tbl.show_on_map) {
    02777             GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK); // outer border of the legend colour
    02778           } else {
    02779             textcol = TC_GREY;
    02780           }
    02781           SetDParam(0, c);
    02782           SetDParam(1, supply);
    02783           DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
    02784           GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour); // legend colour
    02785           y += FONT_HEIGHT_SMALL;
    02786         }
    02787       }
    02788     }
    02789   }
    02790
    02795   void DrawTowns(const DrawPixelInfo *dpi) const
    02796   {
    02797     const Town *t;
    02798     FOR_ALL_TOWNS(t) {
    02799       /* Remap the town coordinate */
    02800       Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
    02801       int x = pt.x - this->subscroll - (t->sign.width_small >> 1);
    02802       int y = pt.y;
    02803
    02804       /* Check if the town sign is within bounds */
    02805       if (x + t->sign.width_small > dpi->left &&
    02806           x < dpi->left + dpi->width &&
    02807           y + FONT_HEIGHT_SMALL > dpi->top &&
    02808           y < dpi->top + dpi->height) {
    02809         /* And draw it. */
    02810         SetDParam(0, t->index);
    02811         DrawString(x, x + t->sign.width_small, y, STR_SMALLMAP_TOWN);
    02812       }
    02813     }
    02814   }
    02815
    02822   static inline void DrawVertMapIndicator(int x, int y, int y2)
    02823   {
    02824     GfxFillRect(x, y,      x, y + 3, PC_VERY_LIGHT_YELLOW);
    02825     GfxFillRect(x, y2 - 3, x, y2,    PC_VERY_LIGHT_YELLOW);
    02826   }
    02827
    02834   static inline void DrawHorizMapIndicator(int x, int x2, int y)
    02835   {
    02836     GfxFillRect(x,      y, x + 3, y, PC_VERY_LIGHT_YELLOW);
    02837     GfxFillRect(x2 - 3, y, x2,    y, PC_VERY_LIGHT_YELLOW);
    02838   }
    02839
    02843   void DrawMapIndicators() const
    02844   {
    02845     /* Find main viewport. */
    02846     const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
    02847
    02848     Point tile = InverseRemapCoords(vp->virtual_left, vp->virtual_top);
    02849     Point tl = this->RemapTile(tile.x >> 4, tile.y >> 4);
    02850     tl.x -= this->subscroll;
    02851
    02852     tile = InverseRemapCoords(vp->virtual_left + vp->virtual_width, vp->virtual_top + vp->virtual_height);
    02853     Point br = this->RemapTile(tile.x >> 4, tile.y >> 4);
    02854     br.x -= this->subscroll;
    02855
    02856     SmallMapWindow::DrawVertMapIndicator(tl.x, tl.y, br.y);
    02857     SmallMapWindow::DrawVertMapIndicator(br.x, tl.y, br.y);
    02858
    02859     SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, tl.y);
    02860     SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, br.y);
    02861   }
    02862
    02874   void DrawSmallMap(DrawPixelInfo *dpi) const
    02875   {
    02876     Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
    02877     DrawPixelInfo *old_dpi;
    02878
    02879     old_dpi = _cur_dpi;
    02880     _cur_dpi = dpi;
    02881
    02882     /* Clear it */
    02883     GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
    02884
    02885     /* Which tile is displayed at (dpi->left, dpi->top)? */
    02886     int dx;
    02887     Point position = this->PixelToWorld(dpi->left, dpi->top, &dx);
    02888     int pos_x = this->scroll_x + position.x;
    02889     int pos_y = this->scroll_y + position.y;
    02890
    02891     void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
    02892     int x = - dx - 4;
    02893     int y = 0;
    02894     int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
    02895
    02896     for (;;) {
    02897       /* Distance from left edge */
    02898       if (x >= -3) {
    02899         if (x >= dpi->width) break; // Exit the loop.
    02900
    02901         int end_pos = min(dpi->width, x + 4);
    02902         int reps = (dpi->height - y + 1) / 2; // Number of lines.
    02903         if (reps > 0) {
    02904           this->DrawSmallMapColumn(ptr, pos_x, pos_y, dpi->pitch * 2, reps, x, end_pos, blitter);
    02905         }
    02906       }
    02907
    02908       if (y == 0) {
    02909         pos_y += increment;
    02910         y++;
    02911         ptr = blitter->MoveTo(ptr, 0, 1);
    02912       } else {
    02913         pos_x -= increment;
    02914         y--;
    02915         ptr = blitter->MoveTo(ptr, 0, -1);
    02916       }
    02917       ptr = blitter->MoveTo(ptr, 2, 0);
    02918       x += 2;
    02919     }
    02920
    02921     /* Draw vehicles */
    02922     if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
    02923
    02924     /* Draw the cargo linkgraphs */
    02925     if (this->map_type == SMT_LINKSTATS && _game_mode == GM_NORMAL) {
    02926       LinkLineDrawer lines;
    02927       this->link_details = lines.DrawLinks(this, true);
    02928
    02929       this->supply_details = DrawStationDots();
    02930
    02931       if (_legend_linkstats[_smallmap_cargo_count + STAT_TEXT].show_on_map) {
    02932         LinkTextDrawer text;
    02933         text.DrawLinks(this, false);
    02934       }
    02935       if (_legend_linkstats[_smallmap_cargo_count + STAT_GRAPH].show_on_map) {
    02936         LinkGraphDrawer graph;
    02937         graph.DrawLinks(this, false);
    02938       }
    02939     }
    02940
    02941     /* Draw town names */
    02942     if (this->show_towns) this->DrawTowns(dpi);
    02943
    02944     /* Draw map indicators */
    02945     this->DrawMapIndicators();
    02946
    02947     _cur_dpi = old_dpi;
    02948   }
    02949
    02950   bool CheckStationSelected(Point *pt) const
    02951   {
    02952     return abs(this->cursor.x - pt->x) < 7 && abs(this->cursor.y - pt->y) < 7;
    02953   }
    02954
    02955   bool CheckLinkSelected(Point *pta, Point *ptb) const
    02956   {
    02957     if (this->cursor.x == -1 && this->cursor.y == -1) return false;
    02958     if (CheckStationSelected(pta) || CheckStationSelected(ptb)) return false;
    02959     if (pta->x > ptb->x) Swap(pta, ptb);
    02960     int minx = min(pta->x, ptb->x);
    02961     int maxx = max(pta->x, ptb->x);
    02962     int miny = min(pta->y, ptb->y);
    02963     int maxy = max(pta->y, ptb->y);
    02964     if (!IsInsideMM(cursor.x, minx - 3, maxx + 3) || !IsInsideMM(cursor.y, miny - 3, maxy + 3)) {
    02965       return false;
    02966     }
    02967
    02968     if (pta->x == ptb->x || ptb->y == pta->y) {
    02969       return true;
    02970     } else {
    02971       int incliney = (ptb->y - pta->y);
    02972       int inclinex = (ptb->x - pta->x);
    02973       int diff = (cursor.x - minx) * incliney / inclinex - (cursor.y - miny);
    02974       if (incliney < 0) {
    02975         diff += maxy - miny;
    02976       }
    02977       return abs(diff) < 4;
    02978     }
    02979   }
    02980
    02984   void RecalcVehiclePositions()
    02985   {
    02986     this->vehicles_on_map.clear();
    02987     const Vehicle *v;
    02988     const NWidgetCore *wi = this->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
    02989     int scale = this->zoom < 0 ? -this->zoom : 1;
    02990
    02991     FOR_ALL_VEHICLES(v) {
    02992       if (v->type == VEH_EFFECT) continue;
    02993       if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
    02994
    02995       /* Remap into flat coordinates. We have to do that again in DrawVehicles to account for scrolling. */
    02996       Point pos = RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
    02997
    02998       /* Check if rhombus is inside bounds */
    02999       if (IsInsideMM(pos.x, -2 * scale, wi->current_x + 2 * scale) &&
    03000         IsInsideMM(pos.y, -2 * scale, wi->current_y + 2 * scale)) {
    03001
    03002         this->vehicles_on_map.push_back(VehicleAndPosition(v));
    03003       }
    03004     }
    03005   }
    03006
    03010   void SetupWidgetData()
    03011   {
    03012     StringID legend_tooltip;
    03013     StringID enable_all_tooltip;
    03014     StringID disable_all_tooltip;
    03015     int plane;
    03016     switch (this->map_type) {
    03017       case SMT_INDUSTRY:
    03018         legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
    03019         enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
    03020         disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
    03021         plane = 0;
    03022         break;
    03023
    03024       case SMT_LINKSTATS:
    03025         legend_tooltip = STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION;
    03026         enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS;
    03027         disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS;
    03028         plane = 0;
    03029         break;
    03030
    03031       case SMT_OWNER:
    03032         legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
    03033         enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
    03034         disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
    03035         plane = 0;
    03036         break;
    03037
    03038       default:
    03039         legend_tooltip = STR_NULL;
    03040         enable_all_tooltip = STR_NULL;
    03041         disable_all_tooltip = STR_NULL;
    03042         plane = 1;
    03043         break;
    03044     }
    03045
    03046     this->GetWidget<NWidgetCore>(SM_WIDGET_LEGEND)->SetDataTip(STR_NULL, legend_tooltip);
    03047     this->GetWidget<NWidgetCore>(SM_WIDGET_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip);
    03048     this->GetWidget<NWidgetCore>(SM_WIDGET_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip);
    03049     this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECT_BUTTONS)->SetDisplayedPlane(plane);
    03050   }
    03051
    03052 public:
    03053   uint min_number_of_columns;
    03054
    03055   SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), supply_details(INVALID_STATION), refresh(FORCE_REFRESH_PERIOD)
    03056   {
    03057     this->cursor.x = -1;
    03058     this->cursor.y = -1;
    03059     this->InitNested(desc, window_number);
    03060     if (_smallmap_cargo_count == 0) {
    03061       this->DisableWidget(SM_WIDGET_LINKSTATS);
    03062       if (this->map_type == SMT_LINKSTATS) this->map_type = SMT_CONTOUR;
    03063     }
    03064
    03065     this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
    03066
    03067     BuildLandLegend();
    03068     this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_show_heightmap);
    03069
    03070     this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
    03071
    03072     this->SetupWidgetData();
    03073
    03074     this->SetZoomLevel(ZLC_INITIALIZE, NULL);
    03075     this->SmallMapCenterOnCurrentPos();
    03076   }
    03077
    03078 //  /**
    03079 //   * Compute maximal required height of the legends. // TODO: remove and fix
    03080 //   * @return Maximally needed height for displaying the smallmap legends in pixels.
    03081 //   */
    03082 //  inline uint GetMaxLegendHeight() const
    03083 //  {
    03084 //    return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + this->GetMaxNumberRowsLegend(this->min_number_of_columns) * FONT_HEIGHT_SMALL;
    03085 //  }
    03086
    03091   inline uint GetMinLegendWidth() const
    03092   {
    03093     return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
    03094   }
    03095
    03100   inline uint GetNumberColumnsLegend(uint width) const
    03101   {
    03102     return width / this->column_width;
    03103   }
    03104
    03111   uint GetLegendHeight(uint num_columns) const
    03112 //  uint GetLegendHeight(uint width) const
    03113   {
    03114 //    uint num_rows = max(this->min_number_of_fixed_rows, CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), num_columns));
    03115 //    return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
    03116 //    uint num_columns = this->GetNumberColumnsLegend(width);
    03117     return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + this->GetNumberRowsLegend(num_columns) * FONT_HEIGHT_SMALL;
    03118   }
    03119
    03120   virtual void SetStringParameters(int widget) const
    03121   {
    03122     switch (widget) {
    03123       case SM_WIDGET_CAPTION:
    03124         SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
    03125         break;
    03126     }
    03127   }
    03128
    03129   virtual void OnInit()
    03130   {
    03131     uint min_width = 0;
    03132     this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
    03133 //    this->min_number_of_fixed_rows = 0;
    03134     this->min_number_of_fixed_rows = lengthof(_legend_linkstats) / 2 + 1;
    03135     if (AllowMoreHeightlevels()) {
    03136       for (uint i = 0; i < lengthof(_legend_table_extended); i++) {
    03137         uint height = 0;
    03138         uint num_columns = 1;
    03139         for (const LegendAndColour *tbl = _legend_table_extended[i]; !tbl->end; ++tbl) {
    03140           StringID str;
    03141           if (i == SMT_INDUSTRY) {
    03142             SetDParam(0, tbl->legend);
    03143             SetDParam(1, IndustryPool::MAX_SIZE);
    03144             str = STR_SMALLMAP_INDUSTRY;
    03145           } else if (i == SMT_LINKSTATS) {
    03146             SetDParam(0, tbl->legend);
    03147             str = STR_SMALLMAP_LINKSTATS;
    03148           } else if (i == SMT_OWNER) {
    03149             if (tbl->company != INVALID_COMPANY) {
    03150               if (!Company::IsValidID(tbl->company)) {
    03151                 /* Rebuild the owner legend. */
    03152                 BuildOwnerLegend();
    03153                 this->OnInit();
    03154                 return;
    03155               }
    03156               /* Non-fixed legend entries for the owner view. */
    03157               SetDParam(0, tbl->company);
    03158               str = STR_SMALLMAP_COMPANY;
    03159             } else {
    03160               str = tbl->legend;
    03161             }
    03162           } else {
    03163             if (tbl->col_break) {
    03164               this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
    03165               height = 0;
    03166               num_columns++;
    03167             }
    03168             height++;
    03169             str = tbl->legend;
    03170           }
    03171           min_width = max(GetStringBoundingBox(str).width, min_width);
    03172         }
    03173         this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
    03174         this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
    03175       }
    03176
    03177     } else {
    03178       for (uint i = 0; i < lengthof(_legend_table_old); i++) {
    03179         uint height = 0;
    03180         uint num_columns = 1;
    03181         for (const LegendAndColour *tbl = _legend_table_old[i]; !tbl->end; ++tbl) {
    03182           StringID str;
    03183           if (i == SMT_INDUSTRY) {
    03184             SetDParam(0, tbl->legend);
    03185             SetDParam(1, IndustryPool::MAX_SIZE);
    03186             str = STR_SMALLMAP_INDUSTRY;
    03187           } else if (i == SMT_LINKSTATS) {
    03188             SetDParam(0, tbl->legend);
    03189             str = STR_SMALLMAP_LINKSTATS;
    03190           } else if (i == SMT_OWNER) {
    03191             if (tbl->company != INVALID_COMPANY) {
    03192               if (!Company::IsValidID(tbl->company)) {
    03193                 /* Rebuild the owner legend. */
    03194                 BuildOwnerLegend();
    03195                 this->OnInit();
    03196                 return;
    03197               }
    03198               /* Non-fixed legend entries for the owner view. */
    03199               SetDParam(0, tbl->company);
    03200               str = STR_SMALLMAP_COMPANY;
    03201             } else {
    03202               str = tbl->legend;
    03203             }
    03204           } else {
    03205             if (tbl->col_break) {
    03206               this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
    03207               height = 0;
    03208               num_columns++;
    03209             }
    03210             height++;
    03211             str = tbl->legend;
    03212           }
    03213           min_width = max(GetStringBoundingBox(str).width, min_width);
    03214         }
    03215         this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
    03216         this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
    03217       }
    03218     }
    03219
    03220     /* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
    03221     this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
    03222   }
    03223
    03224   virtual void OnPaint()
    03225   {
    03226     if (this->map_type == SMT_OWNER) {
    03227       if (AllowMoreHeightlevels()) {
    03228         for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
    03229           if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
    03230             /* Rebuild the owner legend. */
    03231             BuildOwnerLegend();
    03232             this->InvalidateData(1);
    03233             break;
    03234           }
    03235         }
    03236       } else {
    03237         for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
    03238           if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
    03239             /* Rebuild the owner legend. */
    03240             BuildOwnerLegend();
    03241             this->InvalidateData(1);
    03242             break;
    03243           }
    03244         }
    03245       }
    03246     }
    03247
    03248     this->DrawWidgets();
    03249   }
    03250
    03251   virtual void DrawWidget(const Rect &r, int widget) const
    03252   {
    03253     switch (widget) {
    03254       case SM_WIDGET_MAP: {
    03255         DrawPixelInfo new_dpi;
    03256         if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
    03257         this->DrawSmallMap(&new_dpi);
    03258         break;
    03259       }
    03260
    03261       case SM_WIDGET_LEGEND: {
    03262         uint y_org = r.top + WD_FRAMERECT_TOP;
    03263         uint x = r.left + WD_FRAMERECT_LEFT;
    03264         if (this->supply_details != INVALID_STATION) {
    03265           this->DrawSupplyDetails(x, y_org, r.bottom - WD_FRAMERECT_BOTTOM);
    03266         } else if (!this->link_details.Empty()) {
    03267           this->DrawLinkDetails(x, y_org, r.right - WD_FRAMERECT_RIGHT, r.bottom - WD_FRAMERECT_BOTTOM);
    03268         } else {
    03269           uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
    03270           uint number_of_rows = this->GetNumberRowsLegend(columns);
    03271           bool rtl = _current_text_dir == TD_RTL;
    03272           uint y_org = r.top + WD_FRAMERECT_TOP;
    03273           uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
    03274           uint y = y_org;
    03275           uint i = 0; // Row counter for industry legend.
    03276           uint row_height = FONT_HEIGHT_SMALL;
    03277
    03278           uint text_left  = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
    03279           uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
    03280           uint blob_left  = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
    03281           uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
    03282
    03283           StringID string = STR_NULL;
    03284           switch (this->map_type) {
    03285             case SMT_INDUSTRY:
    03286               string = STR_SMALLMAP_INDUSTRY;
    03287               break;
    03288             case SMT_LINKSTATS:
    03289               string = STR_SMALLMAP_LINKSTATS;
    03290               break;
    03291             case SMT_OWNER:
    03292               string = STR_SMALLMAP_COMPANY;
    03293               break;
    03294             default:
    03295               break;
    03296           }
    03297
    03298           if (AllowMoreHeightlevels()) {
    03299             for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
    03300               if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
    03301                 /* Column break needed, continue at top, COLUMN_WIDTH pixels
    03302                  * (one "row") to the right. */
    03303                 x += rtl ? -(int)this->column_width : this->column_width;
    03304                 y = y_org;
    03305                 i = 1;
    03306               }
    03307
    03308               switch(this->map_type) {
    03309                 case SMT_INDUSTRY:
    03310                   /* Industry name must be formatted, since it's not in tiny font in the specs.
    03311                    * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font. */
    03312                   SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
    03313                 case SMT_LINKSTATS:
    03314                   SetDParam(0, tbl->legend);
    03315                 case SMT_OWNER:
    03316                   if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
    03317                     if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
    03318                     if (!tbl->show_on_map) {
    03319                       /* Simply draw the string, not the black border of the legend colour.
    03320                       * This will enforce the idea of the disabled item */
    03321                       DrawString(x + text_left, x + text_right, y, string, TC_GREY);
    03322                     } else {
    03323                       DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
    03324                       GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
    03325                     }
    03326                   break;
    03327                   } // else fall through
    03328                 default:
    03329                   if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
    03330
    03331                   /* Anything that is not an industry or a company is using normal process */
    03332                   GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
    03333                   DrawString(x + text_left, x + text_right, y, tbl->legend);
    03334                   break;
    03335               }
    03336               GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour); // Legend colour.
    03337
    03338               y += row_height;
    03339             }
    03340           } else {
    03341             for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
    03342               if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
    03343                 /* Column break needed, continue at top, COLUMN_WIDTH pixels
    03344                  * (one "row") to the right. */
    03345                 x += rtl ? -(int)this->column_width : this->column_width;
    03346                 y = y_org;
    03347                 i = 1;
    03348               }
    03349
    03350               switch(this->map_type) {
    03351                 case SMT_INDUSTRY:
    03352                   /* Industry name must be formatted, since it's not in tiny font in the specs.
    03353                    * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font. */
    03354                   SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
    03355                 case SMT_LINKSTATS:
    03356                   SetDParam(0, tbl->legend);
    03357                 case SMT_OWNER:
    03358                   if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
    03359                     if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
    03360                     if (!tbl->show_on_map) {
    03361                       /* Simply draw the string, not the black border of the legend colour.
    03362                       * This will enforce the idea of the disabled item */
    03363                       DrawString(x + text_left, x + text_right, y, string, TC_GREY);
    03364                     } else {
    03365                       DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
    03366                       GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
    03367                     }
    03368                   break;
    03369                   } // else fall through
    03370                 default:
    03371                   if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
    03372
    03373                   /* Anything that is not an industry or a company is using normal process */
    03374                   GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
    03375                   DrawString(x + text_left, x + text_right, y, tbl->legend);
    03376                   break;
    03377               }
    03378               GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour); // Legend colour
    03379
    03380               y += row_height;
    03381             }
    03382           }
    03383         }
    03384       } break;
    03385     }
    03386   }
    03387
    03396   uint GetNumberRowsLegend(uint columns) const
    03397   {
    03398     /* reserve one column for link colours */
    03399     uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
    03400
    03401     uint num_rows_others = CeilDiv(max(_smallmap_industry_count,_smallmap_company_count), columns);
    03402     return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
    03403   }
    03404
    03416   void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0)
    03417   {
    03418     if (_ctrl_pressed) {
    03419       /* Disable all, except the clicked one */
    03420       bool changes = false;
    03421       for (int i = begin_legend_item; i != end_legend_item; i++) {
    03422         bool new_state = (i == click_pos);
    03423         if (legend[i].show_on_map != new_state) {
    03424           changes = true;
    03425           legend[i].show_on_map = new_state;
    03426         }
    03427       }
    03428       if (!changes) {
    03429         /* Nothing changed? Then show all (again). */
    03430         for (int i = begin_legend_item; i != end_legend_item; i++) {
    03431           legend[i].show_on_map = true;
    03432         }
    03433       }
    03434     } else {
    03435       legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
    03436     }
    03437   }
    03438
    03443   void SwitchMapType(SmallMapType map_type)
    03444   {
    03445     this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
    03446     this->map_type = map_type;
    03447     this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
    03448
    03449     this->SetupWidgetData();
    03450
    03451     this->SetDirty();
    03452   }
    03453
    03454   virtual void OnClick(Point pt, int widget, int click_count)
    03455   {
    03456     /* User clicked something, notify the industry chain window to stop sending newly selected industries. */
    03457     InvalidateWindowClassesData(WC_INDUSTRY_CARGOES, NUM_INDUSTRYTYPES);
    03458
    03459     switch (widget) {
    03460       case SM_WIDGET_MAP: { // Map window
    03461         /*
    03462          * XXX: scrolling with the left mouse button is done by subsequently
    03463          * clicking with the left mouse button; clicking once centers the
    03464          * large map at the selected point. So by unclicking the left mouse
    03465          * button here, it gets reclicked during the next inputloop, which
    03466          * would make it look like the mouse is being dragged, while it is
    03467          * actually being (virtually) clicked every inputloop.
    03468          */
    03469         _left_button_clicked = false;
    03470
    03471         const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03472
    03473         /* We need to take the height at the clicked position into account
    03474          * (i.e. move the map northwards).
    03475          * Basically, we compute the inverse of function RemapX/Y here.
    03476          * Note that we have to subtract 2 from x and 16 from y here because
    03477          * _cursor_pos.x/y - this->left/top includes the edge of the small map. */
    03478         int offset_inside_sm_x = _cursor.pos.x - this->left + wid->pos_x;
    03479         int offset_inside_sm_y = _cursor.pos.y - this->top - wid->pos_y;
    03480         int clicked_screen_x = offset_inside_sm_x * TILE_SIZE + pt.x;
    03481         int clicked_screen_y = offset_inside_sm_y * TILE_SIZE + pt.y;
    03482         Point clicked_tile = TileCoordFromScreenCoord(clicked_screen_x, clicked_screen_y);
    03483         clicked_tile.x /= TILE_SIZE;
    03484         clicked_tile.y /= TILE_SIZE;
    03485         int clicked_tile_height = TileHeightOutsideMap(clicked_tile.x, clicked_tile.y);
    03486
    03487         DEBUG(map, 9, "clicked: offset_inside_sm (%i,%i), clicked_tile (%i,%i), clicked_screen (%i,%i), clicked_tile_height %i",
    03488             offset_inside_sm_x, offset_inside_sm_y, clicked_tile.x, clicked_tile.y, clicked_screen_x, clicked_screen_y, clicked_tile_height);
    03489
    03490         Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
    03491         int sub;
    03492         pt = this->PixelToWorld(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
    03493         int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
    03494         pt = RemapCoords(this->scroll_x + pt.x + offset - offset * sub / 4,
    03495             this->scroll_y + pt.y + sub * offset / 4, 0);
    03496
    03497         w->viewport->follow_vehicle = INVALID_VEHICLE;
    03498         w->viewport->dest_scrollpos_x = pt.x - (w->viewport->virtual_width  >> 1);
    03499         w->viewport->dest_scrollpos_y = pt.y - ((clicked_tile_height * TILE_HEIGHT) + (w->viewport->virtual_height >> 1)); // TODO: add moreheightlevels_v29 and merge with cargodist (when clicking the smallmap main vieport positioning is slighlty off)
    03500
    03501         DEBUG(map, 9, "OnClick: scroll_x, scroll_y = (%i,%i), pt = (%i,%i), dest_scrollpos = (%i,%i), cursor = (%i,%i), left/top = (%i, %i), virtual = (%i,%i)",
    03502             this->scroll_x, this->scroll_y, pt.x, pt.y,
    03503             w->viewport->dest_scrollpos_x, w->viewport->dest_scrollpos_y,
    03504             _cursor.pos.x, _cursor.pos.y, this->left, this->top,
    03505             w->viewport->virtual_width, w->viewport->virtual_height);
    03506
    03507         this->SetDirty();
    03508         break;
    03509       }
    03510
    03511       case SM_WIDGET_ZOOM_IN:
    03512       case SM_WIDGET_ZOOM_OUT: {
    03513         const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03514         Point pt = {wid->current_x / 2, wid->current_y / 2};
    03515         this->SetZoomLevel((widget == SM_WIDGET_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
    03516         SndPlayFx(SND_15_BEEP);
    03517         break;
    03518       }
    03519
    03520       case SM_WIDGET_CONTOUR:    // Show land contours
    03521       case SM_WIDGET_VEHICLES:   // Show vehicles
    03522       case SM_WIDGET_INDUSTRIES: // Show industries
    03523       case SM_WIDGET_LINKSTATS:  // Show route map
    03524       case SM_WIDGET_ROUTES:     // Show transport routes
    03525       case SM_WIDGET_VEGETATION: // Show vegetation
    03526       case SM_WIDGET_OWNERS:     // Show land owners
    03527         this->SwitchMapType((SmallMapType)(widget - SM_WIDGET_CONTOUR));
    03528         SndPlayFx(SND_15_BEEP);
    03529         break;
    03530
    03531       case SM_WIDGET_CENTERMAP: // Center the smallmap again
    03532         this->SmallMapCenterOnCurrentPos();
    03533         this->HandleButtonClick(SM_WIDGET_CENTERMAP);
    03534         SndPlayFx(SND_15_BEEP);
    03535         break;
    03536
    03537       case SM_WIDGET_TOGGLETOWNNAME: // Toggle town names
    03538         this->show_towns = !this->show_towns;
    03539         this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
    03540
    03541         this->SetDirty();
    03542         SndPlayFx(SND_15_BEEP);
    03543         break;
    03544
    03545       case SM_WIDGET_LEGEND: // Legend
    03546         /* If industry type small map*/
    03547         if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
    03548           /* If click on industries label, find right industry type and enable/disable it */
    03549           const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND); // Label panel
    03550           uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
    03551           uint columns = this->GetNumberColumnsLegend(wi->current_x);
    03552           uint number_of_rows = this->GetNumberRowsLegend(columns);
    03553           if (line >= number_of_rows) break;
    03554
    03555           bool rtl = _current_text_dir == TD_RTL;
    03556           int x = pt.x - wi->pos_x;
    03557           if (rtl) x = wi->current_x - x;
    03558           uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
    03559           int click_pos = (column * number_of_rows) + line;
    03560
    03561           /* Check if click is on industry label*/
    03562           if (this->map_type == SMT_INDUSTRY) {
    03563             if (click_pos < _smallmap_industry_count) {
    03564               this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
    03565             }
    03566           /* Check if click was on linkstats label*/
    03567           } else if (this->map_type == SMT_LINKSTATS) {
    03568             if (click_pos < _smallmap_cargo_count) {
    03569               this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
    03570             } else {
    03571               uint stats_column = CeilDiv(_smallmap_cargo_count, number_of_rows);
    03572               if (column == stats_column && line < NUM_STATS) {
    03573                 this->SelectLegendItem(_smallmap_cargo_count + line, _legend_linkstats,
    03574                     _smallmap_cargo_count + NUM_STATS, _smallmap_cargo_count);
    03575               }
    03576             }
    03577           /* Check if click is on company label. */
    03578           } else if (this->map_type == SMT_OWNER) {
    03579             if (click_pos < _smallmap_company_count) {
    03580             this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
    03581             }
    03582           }
    03583           this->SetDirty();
    03584         }
    03585         break;
    03586
    03587       case SM_WIDGET_ENABLE_ALL: // enable/diable all items
    03588       case SM_WIDGET_DISABLE_ALL: {
    03589         LegendAndColour *tbl = NULL;
    03590           switch (this->map_type) {
    03591             case SMT_INDUSTRY:
    03592               tbl = _legend_from_industries;
    03593               break;
    03594             case SMT_OWNER:
    03595               tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
    03596               break;
    03597             case SMT_LINKSTATS:
    03598               tbl = _legend_linkstats;
    03599               break;
    03600             default:
    03601               NOT_REACHED();
    03602           }
    03603
    03604         for (;!tbl->end; ++tbl) tbl->show_on_map = (widget == SM_WIDGET_ENABLE_ALL);
    03605         this->SetDirty();
    03606         break;
    03607       }
    03608
    03609       case SM_WIDGET_SHOW_HEIGHT: // Enable/disable showing of heightmap.
    03610         _smallmap_show_heightmap = !_smallmap_show_heightmap;
    03611         this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_show_heightmap);
    03612         this->SetDirty();
    03613         break;
    03614     }
    03615   }
    03616
    03617   virtual void OnMouseOver(Point pt, int widget)
    03618   {
    03619     static Point invalid = {-1, -1};
    03620     if (widget == SM_WIDGET_MAP) {
    03621       const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03622       pt.x -= wid->pos_x;
    03623       pt.y -= wid->pos_y;
    03624       if (pt.x != cursor.x || pt.y != cursor.y) {
    03625         this->refresh = 1;
    03626         cursor = pt;
    03627       }
    03628     } else {
    03629       cursor = invalid;
    03630     }
    03631   }
    03632
    03640   virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
    03641   {
    03642     if (!gui_scope) return;
    03643     switch (data) {
    03644       case 1:
    03645         /* The owner legend has already been rebuilt. */
    03646         this->ReInit();
    03647         break;
    03648
    03649       case 0: {
    03650         extern uint64 _displayed_industries;
    03651         if (this->map_type != SMT_INDUSTRY) this->SwitchMapType(SMT_INDUSTRY);
    03652
    03653         for (int i = 0; i != _smallmap_industry_count; i++) {
    03654           _legend_from_industries[i].show_on_map = HasBit(_displayed_industries, _legend_from_industries[i].type);
    03655         }
    03656         break;
    03657       }
    03658
    03659       default: NOT_REACHED();
    03660     }
    03661     this->SetDirty();
    03662   }
    03663
    03664   virtual bool OnRightClick(Point pt, int widget)
    03665   {
    03666     if (widget != SM_WIDGET_MAP || _scrolling_viewport) return false;
    03667
    03668     _scrolling_viewport = true;
    03669     return true;
    03670   }
    03671
    03672   virtual void OnMouseWheel(int wheel)
    03673   {
    03674     if (_settings_client.gui.scrollwheel_scrolling == 0) {
    03675       const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03676       int cursor_x = _cursor.pos.x - this->left - wid->pos_x;
    03677       int cursor_y = _cursor.pos.y - this->top  - wid->pos_y;
    03678       if (IsInsideMM(cursor_x, 0, wid->current_x) && IsInsideMM(cursor_y, 0, wid->current_y)) {
    03679         Point pt = {cursor_x, cursor_y};
    03680         this->SetZoomLevel((wheel < 0) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
    03681       }
    03682     }
    03683   }
    03684
    03685   virtual void OnTick()
    03686   {
    03687     /* Update the window every now and then */
    03688     if (--this->refresh != 0) return;
    03689
    03690     this->RecalcVehiclePositions();
    03691
    03692     this->refresh = FORCE_REFRESH_PERIOD;
    03693     this->SetDirty();
    03694   }
    03695
    03703   void SetNewScroll(int sx, int sy, int sub)
    03704   {
    03705     const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03706     Point hv = InverseRemapCoords(wi->current_x * TILE_SIZE / 2, wi->current_y * TILE_SIZE / 2);
    03707     if (this->zoom > 0) {
    03708       hv.x *= this->zoom;
    03709       hv.y *= this->zoom;
    03710     } else {
    03711       hv.x /= (-this->zoom);
    03712       hv.y /= (-this->zoom);
    03713     }
    03714
    03715     if (sx < -hv.x) {
    03716       sx = -hv.x;
    03717       sub = 0;
    03718     }
    03719     if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
    03720       sx = MapMaxX() * TILE_SIZE - hv.x;
    03721       sub = 0;
    03722     }
    03723     if (sy < -hv.y) {
    03724       sy = -hv.y;
    03725       sub = 0;
    03726     }
    03727     if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
    03728       sy = MapMaxY() * TILE_SIZE - hv.y;
    03729       sub = 0;
    03730     }
    03731
    03732     this->scroll_x = sx;
    03733     this->scroll_y = sy;
    03734     this->subscroll = sub;
    03735   }
    03736
    03737   virtual void OnScroll(Point delta)
    03738   {
    03739     _cursor.fix_at = true;
    03740
    03741     /* While tile is at (delta.x, delta.y)? */
    03742     int sub;
    03743     Point pt = this->PixelToWorld(delta.x, delta.y, &sub);
    03744     this->SetNewScroll(this->scroll_x + pt.x, this->scroll_y + pt.y, sub);
    03745
    03746     this->SetDirty();
    03747   }
    03748
    03749   void SmallMapCenterOnCurrentPos()
    03750   {
    03751     const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
    03752     Point pt = InverseRemapCoords(vp->virtual_left + vp->virtual_width  / 2, vp->virtual_top  + vp->virtual_height / 2);
    03753
    03754     int sub;
    03755     const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
    03756     Point sxy = this->ComputeScroll(pt.x, pt.y, max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
    03757     this->SetNewScroll(sxy.x, sxy.y, sub);
    03758     this->SetDirty();
    03759   }
    03760
    03761   uint ColumnWidth() const {return column_width;}
    03762 };
    03763
    03764 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
    03765 bool SmallMapWindow::show_towns = true;
    03766
    03775 class NWidgetSmallmapDisplay : public NWidgetContainer {
    03776   const SmallMapWindow *smallmap_window;
    03777 public:
    03778   NWidgetSmallmapDisplay() : NWidgetContainer(NWID_VERTICAL)
    03779   {
    03780     this->smallmap_window = NULL;
    03781   }
    03782
    03783   virtual void SetupSmallestSize(Window *w, bool init_array)
    03784   {
    03785     NWidgetBase *display = this->head;
    03786     NWidgetBase *bar = display->next;
    03787
    03788     display->SetupSmallestSize(w, init_array);
    03789     bar->SetupSmallestSize(w, init_array);
    03790
    03791     this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
    03792     this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
    03793     this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
    03794 //    this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight());
    03795     this->fill_x = max(display->fill_x, bar->fill_x);
    03796     this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
    03797     this->resize_x = max(display->resize_x, bar->resize_x);
    03798     this->resize_y = min(display->resize_y, bar->resize_y);
    03799   }
    03800
    03801   virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
    03802   {
    03803     this->pos_x = x;
    03804     this->pos_y = y;
    03805     this->current_x = given_width;
    03806     this->current_y = given_height;
    03807
    03808     NWidgetBase *display = this->head;
    03809     NWidgetBase *bar = display->next;
    03810
    03811     if (sizing == ST_SMALLEST) {
    03812       this->smallest_x = given_width;
    03813       this->smallest_y = given_height;
    03814       /* Make display and bar exactly equal to their minimal size. */
    03815       display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
    03816       bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
    03817     }
    03818
    03819 //    uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
    03820     uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
    03821     uint display_height = given_height - bar_height;
    03822     display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
    03823     bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
    03824   }
    03825
    03826   virtual NWidgetCore *GetWidgetFromPos(int x, int y)
    03827   {
    03828     if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
    03829     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    03830       NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
    03831       if (widget != NULL) return widget;
    03832     }
    03833     return NULL;
    03834   }
    03835
    03836   virtual void Draw(const Window *w)
    03837   {
    03838     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
    03839   }
    03840 };
    03841
    03843 static const NWidgetPart _nested_smallmap_display[] = {
    03844   NWidget(WWT_PANEL, COLOUR_BROWN, SM_WIDGET_MAP_BORDER),
    03845     NWidget(WWT_INSET, COLOUR_BROWN, SM_WIDGET_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
    03846   EndContainer(),
    03847 };
    03848
    03850 static const NWidgetPart _nested_smallmap_bar[] = {
    03851   NWidget(WWT_PANEL, COLOUR_BROWN),
    03852     NWidget(NWID_HORIZONTAL),
    03853       NWidget(WWT_EMPTY, INVALID_COLOUR, SM_WIDGET_LEGEND), SetResize(1, 1),
    03854       NWidget(NWID_VERTICAL),
    03855         /* Top button row. */
    03856         NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
    03857           NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_IN),
    03858               SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
    03859           NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP),
    03860               SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
    03861           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_BLANK), SetMinimalSize(22, 22),
    03862               SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
    03863           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR),
    03864               SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
    03865           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES),
    03866               SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
    03867           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES),
    03868               SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
    03869         EndContainer(),
    03870         /* Bottom button row. */
    03871         NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
    03872           NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_OUT),
    03873               SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
    03874           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME),
    03875               SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
    03876           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_LINKSTATS),
    03877               SetDataTip(SPR_IMG_GRAPHS, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
    03878           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES),
    03879               SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
    03880           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION),
    03881               SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
    03882           NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS),
    03883               SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
    03884         EndContainer(),
    03885         NWidget(NWID_SPACER), SetResize(0, 1),
    03886       EndContainer(),
    03887     EndContainer(),
    03888   EndContainer(),
    03889 };
    03890
    03891 static NWidgetBase *SmallMapDisplay(int *biggest_index)
    03892 {
    03893   NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
    03894
    03895   MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
    03896   MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
    03897   return map_display;
    03898 }
    03899
    03900
    03901 static const NWidgetPart _nested_smallmap_widgets[] = {
    03902   NWidget(NWID_HORIZONTAL),
    03903     NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
    03904     NWidget(WWT_CAPTION, COLOUR_BROWN, SM_WIDGET_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
    03905     NWidget(WWT_SHADEBOX, COLOUR_BROWN),
    03906     NWidget(WWT_STICKYBOX, COLOUR_BROWN),
    03907   EndContainer(),
    03908   NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons.
    03909   /* Bottom button row and resize box. */
    03910   NWidget(NWID_HORIZONTAL),
    03911     NWidget(WWT_PANEL, COLOUR_BROWN),
    03912       NWidget(NWID_HORIZONTAL),
    03913         NWidget(NWID_SELECTION, INVALID_COLOUR, SM_WIDGET_SELECT_BUTTONS),
    03914           NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
    03915             NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, SM_WIDGET_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL),
    03916             NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, SM_WIDGET_DISABLE_ALL), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_NULL),
    03917             NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
    03918           EndContainer(),
    03919           NWidget(NWID_SPACER), SetFill(1, 1),
    03920         EndContainer(),
    03921         NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
    03922       EndContainer(),
    03923     EndContainer(),
    03924     NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
    03925   EndContainer(),
    03926 };
    03927
    03928 static const WindowDesc _smallmap_desc(
    03929   WDP_AUTO, 484, 314,
    03930   WC_SMALLMAP, WC_NONE,
    03931   WDF_UNCLICK_BUTTONS,
    03932   _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
    03933 );
    03934
    03938 void ShowSmallMap()
    03939 {
    03940   AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
    03941 }
    03942
    03951 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
    03952 {
    03953   bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
    03954
    03955   /* If a user scrolls to a tile (via what way what so ever) and already is on
    03956    * that tile (e.g.: pressed twice), move the smallmap to that location,
    03957    * so you directly see where you are on the smallmap. */
    03958
    03959   if (res) return res;
    03960
    03961   SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
    03962   if (w != NULL) w->SmallMapCenterOnCurrentPos();
    03963
    03964   return res;
    03965 }