src/industry_gui.cpp
branchNewGRF_ports
changeset 6720 35756db7e577
parent 6719 4cc327ad39d5
child 6730 f09255ea0123
equal deleted inserted replaced
6719:4cc327ad39d5 6720:35756db7e577
    18 #include "industry.h"
    18 #include "industry.h"
    19 #include "town.h"
    19 #include "town.h"
    20 #include "variables.h"
    20 #include "variables.h"
    21 #include "helpers.hpp"
    21 #include "helpers.hpp"
    22 #include "cargotype.h"
    22 #include "cargotype.h"
    23 
    23 #include "newgrf.h"
    24 /* industries per climate, according to the different construction windows */
    24 #include "newgrf_callbacks.h"
    25 const byte _build_industry_types[4][12] = {
    25 #include "newgrf_industries.h"
    26 	{  1,  2,  4,  6,  8,  0,  3,  5,  9, 11, 18 },
    26 #include "newgrf_text.h"
    27 	{  1, 14,  4, 13,  7,  0,  3,  9, 11, 15 },
    27 
    28 	{ 25, 13,  4, 23, 22, 11, 17, 10, 24, 19, 20, 21 },
    28 extern Industry *CreateNewIndustry(TileIndex tile, IndustryType type);
    29 	{ 27, 30, 31, 33, 26, 28, 29, 32, 34, 35, 36 },
    29 
       
    30 /**
       
    31  * Search callback function for TryBuildIndustry
       
    32  * @param tile to test
       
    33  * @param data that is passed by the caller.  In this case, the type of industry been tested
       
    34  * @return the success (or not) of the operation
       
    35  */
       
    36 static bool SearchTileForIndustry(TileIndex tile, uint32 data)
       
    37 {
       
    38 	return CreateNewIndustry(tile, data) != NULL;
       
    39 }
       
    40 
       
    41 /**
       
    42  * Perform a 9*9 tiles circular search around a tile
       
    43  * in order to find a suitable zone to create the desired industry
       
    44  * @param tile to start search for
       
    45  * @param type of the desired industry
       
    46  * @return the success (or not) of the operation
       
    47  */
       
    48 static bool TryBuildIndustry(TileIndex tile, int type)
       
    49 {
       
    50 	return CircularTileSearch(tile, 9, SearchTileForIndustry, type);
       
    51 }
       
    52 bool _ignore_restrictions;
       
    53 
       
    54 enum {
       
    55 	DYNA_INDU_MATRIX_WIDGET = 2,
       
    56 	DYNA_INDU_INFOPANEL = 4,
       
    57 	DYNA_INDU_FUND_WIDGET,
       
    58 	DYNA_INDU_RESIZE_WIDGET,
    30 };
    59 };
    31 
    60 
    32 static void UpdateIndustryProduction(Industry *i);
    61 static struct IndustryData {
    33 
    62 	uint16 count;
    34 static void BuildIndustryWndProc(Window *w, WindowEvent *e)
    63 	IndustryType select;
       
    64 	byte index[NUM_INDUSTRYTYPES + 1];
       
    65 	StringID additional_text[NUM_INDUSTRYTYPES + 1];
       
    66 } _industrydata;
       
    67 
       
    68 static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
    35 {
    69 {
    36 	switch (e->event) {
    70 	switch (e->event) {
    37 	case WE_PAINT:
    71 		case WE_CREATE: {
    38 		DrawWindowWidgets(w);
    72 			IndustryType ind;
    39 		if (_thd.place_mode == 1 && _thd.window_class == WC_BUILD_INDUSTRY) {
    73 			const IndustrySpec *indsp;
    40 			int ind_type = _build_industry_types[_opt_ptr->landscape][WP(w, def_d).data_1];
    74 
    41 
    75 			/* Shorten the window to the equivalant of the additionnal purchase
    42 			SetDParam(0, (_price.build_industry >> 5) * GetIndustrySpec(ind_type)->cost_multiplier);
    76 			 * info coming from the callback.  SO it will only be available to tis full
    43 			DrawStringCentered(85, w->height - 21, STR_482F_COST, 0);
    77 			 * height when newindistries are loaded */
    44 		}
    78 			if (!_loaded_newgrf_features.has_newindustries) {
    45 		break;
    79 				w->widget[DYNA_INDU_INFOPANEL].bottom -= 44;
    46 
    80 				w->widget[DYNA_INDU_FUND_WIDGET].bottom -= 44;
    47 	case WE_CLICK: {
    81 				w->widget[DYNA_INDU_FUND_WIDGET].top -= 44;
    48 		int wid = e->we.click.widget;
    82 				w->widget[DYNA_INDU_RESIZE_WIDGET].bottom -= 44;
    49 		if (wid >= 3) {
    83 				w->widget[DYNA_INDU_RESIZE_WIDGET].top -= 44;
    50 			if (HandlePlacePushButton(w, wid, SPR_CURSOR_INDUSTRY, 1, NULL))
    84 				w->resize.height = w->height -= 44;
    51 				WP(w, def_d).data_1 = wid - 3;
    85 			}
    52 		}
    86 
       
    87 			/* Initilialize structures */
       
    88 			memset(&_industrydata.index, 0xFF, NUM_INDUSTRYTYPES);
       
    89 			memset(&_industrydata.additional_text, STR_NULL, NUM_INDUSTRYTYPES);
       
    90 			_industrydata.count = 0;
       
    91 
       
    92 			/* first indutry type is selected.
       
    93 			 * I'll be damned if there are none available ;) */
       
    94 			_industrydata.select = 0;
       
    95 			w->vscroll.cap = 8; // rows in grid, same in scroller
       
    96 			w->resize.step_height = 13;
       
    97 
       
    98 			if (_game_mode == GM_EDITOR) { // give room for the Many Random "button"
       
    99 				_industrydata.index[_industrydata.count] = INVALID_INDUSTRYTYPE;
       
   100 				_industrydata.count++;
       
   101 			}
       
   102 
       
   103 			/* We'll perform two distinct loops, one for secondary industries, and the other one for
       
   104 			 * primary ones. Each loop will fill the _industrydata structure. */
       
   105 			for (ind = IT_COAL_MINE; ind < NUM_INDUSTRYTYPES; ind++) {
       
   106 				indsp = GetIndustrySpec(ind);
       
   107 				if (indsp->enabled && (!indsp->IsRawIndustry() || _game_mode == GM_EDITOR)) {
       
   108 					_industrydata.index[_industrydata.count] = ind;
       
   109 					_industrydata.count++;
       
   110 				}
       
   111 			}
       
   112 
       
   113 			if (_patches.raw_industry_construction != 0 && _game_mode != GM_EDITOR) {
       
   114 				for (ind = IT_COAL_MINE; ind < NUM_INDUSTRYTYPES; ind++) {
       
   115 					indsp = GetIndustrySpec(ind);
       
   116 					if (indsp->enabled && indsp->IsRawIndustry()) {
       
   117 						_industrydata.index[_industrydata.count] = ind;
       
   118 						_industrydata.count++;
       
   119 					}
       
   120 				}
       
   121 			}
       
   122 		} break;
       
   123 
       
   124 		case WE_PAINT: {
       
   125 			const IndustrySpec *indsp = (_industrydata.index[_industrydata.select] == INVALID_INDUSTRYTYPE) ? NULL : GetIndustrySpec(_industrydata.index[_industrydata.select]);
       
   126 			StringID str = STR_4827_REQUIRES;
       
   127 			int x_str = w->widget[DYNA_INDU_INFOPANEL].left + 3;
       
   128 			int y_str = w->widget[DYNA_INDU_INFOPANEL].top + 3;
       
   129 			const Widget *wi = &w->widget[DYNA_INDU_INFOPANEL];
       
   130 			int max_width = wi->right - wi->left - 4;
       
   131 
       
   132 			/* Raw industries might be prospected. Show this fact by changing the string */
       
   133 			if (_game_mode == GM_EDITOR) {
       
   134 				w->widget[DYNA_INDU_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY;
       
   135 			} else {
       
   136 				w->widget[DYNA_INDU_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY;
       
   137 			}
       
   138 
       
   139 			SetVScrollCount(w, _industrydata.count);
       
   140 
       
   141 			DrawWindowWidgets(w);
       
   142 
       
   143 			/* and now with the matrix painting */
       
   144 			for (byte i = 0; i < w->vscroll.cap && ((i + w->vscroll.pos) < _industrydata.count); i++) {
       
   145 				int offset = i * 13;
       
   146 				int x = 3;
       
   147 				int y = 16;
       
   148 				bool selected = _industrydata.select == i + w->vscroll.pos;
       
   149 
       
   150 				if (_industrydata.index[i + w->vscroll.pos] == INVALID_INDUSTRYTYPE) {
       
   151 					DrawString(21, y + offset, STR_MANY_RANDOM_INDUSTRIES, selected ? 12 : 6);
       
   152 					continue;
       
   153 				}
       
   154 				const IndustrySpec *indsp = GetIndustrySpec(_industrydata.index[i + w->vscroll.pos]);
       
   155 
       
   156 				/* Draw the name of the industry in white is selected, otherwise, in orange */
       
   157 				DrawString(20,     y + offset, indsp->name, selected ? 12 : 6);
       
   158 				GfxFillRect(x,     y + 1 + offset,  x + 10, y + 7 + offset, selected ? 15 : 0);
       
   159 				GfxFillRect(x + 1, y + 2 + offset,  x +  9, y + 6 + offset, indsp->map_colour);
       
   160 			}
       
   161 
       
   162 			if (_industrydata.index[_industrydata.select] == INVALID_INDUSTRYTYPE) {
       
   163 				DrawStringMultiLine(x_str, y_str, STR_RANDOM_INDUSTRIES_TIP, max_width, wi->bottom - wi->top - 40);
       
   164 				break;
       
   165 			}
       
   166 
       
   167 			if (_game_mode != GM_EDITOR) {
       
   168 				SetDParam(0, indsp->GetConstructionCost());
       
   169 				DrawStringTruncated(x_str, y_str, STR_482F_COST, 0, max_width);
       
   170 				y_str += 11;
       
   171 			}
       
   172 
       
   173 			/* Draw the accepted cargos, if any. Otherwhise, will print "Nothing" */
       
   174 			if (indsp->accepts_cargo[0] != CT_INVALID) {
       
   175 				SetDParam(0, GetCargo(indsp->accepts_cargo[0])->name);
       
   176 				if (indsp->accepts_cargo[1] != CT_INVALID) {
       
   177 					SetDParam(1, GetCargo(indsp->accepts_cargo[1])->name);
       
   178 					str = STR_4828_REQUIRES;
       
   179 					if (indsp->accepts_cargo[2] != CT_INVALID) {
       
   180 						SetDParam(2, GetCargo(indsp->accepts_cargo[2])->name);
       
   181 						str = STR_4829_REQUIRES;
       
   182 					}
       
   183 				}
       
   184 			} else {
       
   185 				SetDParam(0, STR_00D0_NOTHING);
       
   186 			}
       
   187 			DrawStringTruncated(x_str, y_str, str, 0, max_width);
       
   188 
       
   189 			y_str += 11;
       
   190 			/* Draw the produced cargos, if any. Otherwhise, will print "Nothing" */
       
   191 			str = STR_4827_PRODUCES;
       
   192 			if (indsp->produced_cargo[0] != CT_INVALID) {
       
   193 				SetDParam(0, GetCargo(indsp->produced_cargo[0])->name);
       
   194 				if (indsp->produced_cargo[1] != CT_INVALID) {
       
   195 					SetDParam(1, GetCargo(indsp->produced_cargo[1])->name);
       
   196 					str = STR_4828_PRODUCES;
       
   197 				}
       
   198 			} else {
       
   199 				SetDParam(0, STR_00D0_NOTHING);
       
   200 			}
       
   201 			DrawStringTruncated(x_str, y_str, str, 0, max_width);
       
   202 
       
   203 			/* Get the additional purchase info text, if it has not already been */
       
   204 			if (_industrydata.additional_text[_industrydata.select] == STR_NULL) {   // Have i been called already?
       
   205 				if (HASBIT(indsp->callback_flags, CBM_IND_FUND_MORE_TEXT)) {          // No. Can it be called?
       
   206 					uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, _industrydata.index[_industrydata.select], INVALID_TILE);
       
   207 					if (callback_res != CALLBACK_FAILED) {  // Did it failed?
       
   208 						StringID newtxt = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res);  // No. here's the new string
       
   209 						_industrydata.additional_text[_industrydata.select] = newtxt;   // Store it for further usage
       
   210 					}
       
   211 				}
       
   212 			}
       
   213 
       
   214 			y_str += 11;
       
   215 			/* Draw the Additional purchase text, provided by newgrf callback, if any.
       
   216 			 * Otherwhise, will print Nothing */
       
   217 			if (_industrydata.additional_text[_industrydata.select] != STR_NULL &&
       
   218 					_industrydata.additional_text[_industrydata.select] != STR_UNDEFINED) {
       
   219 
       
   220 				SetDParam(0, _industrydata.additional_text[_industrydata.select]);
       
   221 				DrawStringMultiLine(x_str, y_str, STR_JUST_STRING, max_width, wi->bottom - wi->top - 40);  // text is white, for now
       
   222 			}
       
   223 		} break;
       
   224 
       
   225 		case WE_CLICK:
       
   226 			switch (e->we.click.widget) {
       
   227 				case DYNA_INDU_MATRIX_WIDGET: {
       
   228 					IndustryType type;
       
   229 					int y = (e->we.click.pt.y - w->widget[DYNA_INDU_MATRIX_WIDGET].top) / 13 + w->vscroll.pos ;
       
   230 
       
   231 					if (y >= 0 && y < _industrydata.count) { //Isit within the boundaries of available data?
       
   232 						_industrydata.select = y;
       
   233 						type = _industrydata.index[_industrydata.select];
       
   234 
       
   235 						SetWindowDirty(w);
       
   236 						if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 &&	GetIndustrySpec(type)->IsRawIndustry()) ||
       
   237 								type == INVALID_INDUSTRYTYPE) {
       
   238 							/* Reset the button state if going to prospecting or "build many industries" */
       
   239 							RaiseWindowButtons(w);
       
   240 							ResetObjectToPlace();
       
   241 						}
       
   242 					}
       
   243 				} break;
       
   244 
       
   245 				case DYNA_INDU_FUND_WIDGET: {
       
   246 					IndustryType type = _industrydata.index[_industrydata.select];
       
   247 
       
   248 					if (type == INVALID_INDUSTRYTYPE) {
       
   249 						HandleButtonClick(w, DYNA_INDU_FUND_WIDGET);
       
   250 						WP(w, def_d).data_1 = -1;
       
   251 
       
   252 						if (GetNumTowns() == 0) {
       
   253 							ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_CAN_T_GENERATE_INDUSTRIES, 0, 0);
       
   254 						} else {
       
   255 							extern void GenerateIndustries();
       
   256 							_generating_world = true;
       
   257 							GenerateIndustries();
       
   258 							_generating_world = false;
       
   259 						}
       
   260 					} else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(type)->IsRawIndustry()) {
       
   261 						DoCommandP(0, type, 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
       
   262 						HandleButtonClick(w, DYNA_INDU_FUND_WIDGET);
       
   263 						WP(w, def_d).data_1 = -1;
       
   264 					} else if (HandlePlacePushButton(w, DYNA_INDU_FUND_WIDGET, SPR_CURSOR_INDUSTRY, 1, NULL)) {
       
   265 							WP(w, def_d).data_1 = _industrydata.select;
       
   266 					}
       
   267 				}
       
   268 				break;
    53 	} break;
   269 	} break;
    54 
   270 
    55 	case WE_PLACE_OBJ:
   271 	case WE_RESIZE: {
    56 		if (DoCommandP(e->we.place.tile, _build_industry_types[_opt_ptr->landscape][WP(w, def_d).data_1], 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)))
   272 		w->vscroll.cap  += e->we.sizing.diff.y / (int)w->resize.step_height;
       
   273 		w->widget[DYNA_INDU_MATRIX_WIDGET].data = (w->vscroll.cap << 8) + 1;
       
   274 	} break;
       
   275 
       
   276 	case WE_PLACE_OBJ: {
       
   277 		IndustryType type = _industrydata.index[_industrydata.select];
       
   278 
       
   279 		if (WP(w, def_d).data_1 == -1) break;
       
   280 		if (_game_mode == GM_EDITOR) {
       
   281 			/* Show error if no town exists at all */
       
   282 			if (GetNumTowns() == 0) {
       
   283 				SetDParam(0, GetIndustrySpec(type)->name);
       
   284 				ShowErrorMessage(STR_0286_MUST_BUILD_TOWN_FIRST, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
       
   285 				return;
       
   286 			}
       
   287 
       
   288 			_current_player = OWNER_NONE;
       
   289 			_generating_world = true;
       
   290 			_ignore_restrictions = true;
       
   291 			if (!TryBuildIndustry(e->we.place.tile, type)) {
       
   292 				SetDParam(0, GetIndustrySpec(type)->name);
       
   293 				ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
       
   294 			} else {
       
   295 				ResetObjectToPlace();
       
   296 			}
       
   297 			_ignore_restrictions = false;
       
   298 			_generating_world = false;
       
   299 		} else if (DoCommandP(e->we.place.tile, type, 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY))) {
    57 			ResetObjectToPlace();
   300 			ResetObjectToPlace();
    58 		break;
   301 		}
       
   302 	} break;
    59 
   303 
    60 	case WE_ABORT_PLACE_OBJ:
   304 	case WE_ABORT_PLACE_OBJ:
    61 		RaiseWindowButtons(w);
   305 		RaiseWindowButtons(w);
    62 		break;
   306 		break;
       
   307 
       
   308 	case WE_TIMEOUT:
       
   309 		if (WP(w, def_d).data_1 == -1) {
       
   310 			RaiseWindowButtons(w);
       
   311 			WP(w, def_d).data_1 = 0;
       
   312 		}
       
   313 		break;
    63 	}
   314 	}
    64 }
   315 }
    65 
   316 
    66 static const Widget _build_industry_land0_widgets[] = {
   317 static const Widget _build_dynamic_industry_widgets[] = {
    67 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
   318 {   WWT_CLOSEBOX,    RESIZE_NONE,    7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
    68 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
   319 {    WWT_CAPTION,   RESIZE_RIGHT,    7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
    69 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   115, 0x0,                            STR_NULL},
   320 {     WWT_MATRIX,      RESIZE_RB,    7,     0,   157,    14,   118, 0x801,                          STR_INDUSTRY_SELECTION_HINT},
    70 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0241_POWER_STATION,         STR_0263_CONSTRUCT_POWER_STATION},
   321 {  WWT_SCROLLBAR,     RESIZE_LRB,    7,   158,   169,    14,   118, 0x0,                            STR_0190_SCROLL_BAR_SCROLLS_LIST},
    71 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_0242_SAWMILL,               STR_0264_CONSTRUCT_SAWMILL},
   322 {      WWT_PANEL,     RESIZE_RTB,    7,     0,   169,   119,   199, 0x0,                            STR_NULL},
    72 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
   323 {    WWT_TEXTBTN,     RESIZE_RTB,    7,     0,   157,   200,   211, STR_FUND_NEW_INDUSTRY,          STR_NULL},
    73 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_0246_FACTORY,               STR_0268_CONSTRUCT_FACTORY},
   324 {  WWT_RESIZEBOX,    RESIZE_LRTB,    7,   158,   169,   200,   211, 0x0,                            STR_RESIZE_BUTTON},
    74 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_0247_STEEL_MILL,            STR_0269_CONSTRUCT_STEEL_MILL},
       
    75 {   WIDGETS_END},
   325 {   WIDGETS_END},
    76 };
   326 };
    77 
   327 
    78 static const Widget _build_industry_land1_widgets[] = {
   328 static const WindowDesc _build_industry_dynamic_desc = {
    79 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
   329 	WDP_AUTO, WDP_AUTO, 170, 212,
    80 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
   330 	WC_BUILD_INDUSTRY, WC_NONE,
    81 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   115, 0x0,                            STR_NULL},
   331 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
    82 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0241_POWER_STATION,         STR_0263_CONSTRUCT_POWER_STATION},
   332 	_build_dynamic_industry_widgets,
    83 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_024C_PAPER_MILL,            STR_026E_CONSTRUCT_PAPER_MILL},
   333 	BuildDynamicIndustryWndProc,
    84 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
       
    85 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING},
       
    86 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_024E_PRINTING_WORKS,        STR_0270_CONSTRUCT_PRINTING_WORKS},
       
    87 {   WIDGETS_END},
       
    88 };
   334 };
    89 
   335 
    90 static const Widget _build_industry_land2_widgets[] = {
       
    91 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
    92 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
    93 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   115, 0x0,                            STR_NULL},
       
    94 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0250_LUMBER_MILL,           STR_0273_CONSTRUCT_LUMBER_MILL_TO},
       
    95 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING},
       
    96 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
       
    97 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_0246_FACTORY,               STR_0268_CONSTRUCT_FACTORY},
       
    98 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_0254_WATER_TOWER,           STR_0277_CONSTRUCT_WATER_TOWER_CAN},
       
    99 {   WIDGETS_END},
       
   100 };
       
   101 
       
   102 static const Widget _build_industry_land3_widgets[] = {
       
   103 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
   104 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   105 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   115, 0x0,                            STR_NULL},
       
   106 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0258_CANDY_FACTORY,         STR_027B_CONSTRUCT_CANDY_FACTORY},
       
   107 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_025B_TOY_SHOP,              STR_027E_CONSTRUCT_TOY_SHOP},
       
   108 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_025C_TOY_FACTORY,           STR_027F_CONSTRUCT_TOY_FACTORY},
       
   109 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_025E_FIZZY_DRINK_FACTORY,   STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
       
   110 {   WIDGETS_END},
       
   111 };
       
   112 
       
   113 static const Widget _build_industry_land0_widgets_extra[] = {
       
   114 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
   115 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   116 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   187, 0x0,                            STR_NULL},
       
   117 
       
   118 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0241_POWER_STATION,         STR_0263_CONSTRUCT_POWER_STATION},
       
   119 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_0242_SAWMILL,               STR_0264_CONSTRUCT_SAWMILL},
       
   120 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
       
   121 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_0246_FACTORY,               STR_0268_CONSTRUCT_FACTORY},
       
   122 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_0247_STEEL_MILL,            STR_0269_CONSTRUCT_STEEL_MILL},
       
   123 
       
   124 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    84,    95, STR_0240_COAL_MINE,             STR_CONSTRUCT_COAL_MINE_TIP},
       
   125 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    97,   108, STR_0243_FOREST,                STR_CONSTRUCT_FOREST_TIP},
       
   126 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   110,   121, STR_0245_OIL_RIG,               STR_CONSTRUCT_OIL_RIG_TIP},
       
   127 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   123,   134, STR_0248_FARM,                  STR_CONSTRUCT_FARM_TIP},
       
   128 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   136,   147, STR_024A_OIL_WELLS,             STR_CONSTRUCT_OIL_WELLS_TIP},
       
   129 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   149,   160, STR_0249_IRON_ORE_MINE,         STR_CONSTRUCT_IRON_ORE_MINE_TIP},
       
   130 
       
   131 {   WIDGETS_END},
       
   132 };
       
   133 
       
   134 static const Widget _build_industry_land1_widgets_extra[] = {
       
   135 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
   136 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   137 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   174, 0x0,                            STR_NULL},
       
   138 
       
   139 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0241_POWER_STATION,         STR_0263_CONSTRUCT_POWER_STATION},
       
   140 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_024C_PAPER_MILL,            STR_026E_CONSTRUCT_PAPER_MILL},
       
   141 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
       
   142 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING},
       
   143 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_024E_PRINTING_WORKS,        STR_0270_CONSTRUCT_PRINTING_WORKS},
       
   144 
       
   145 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    84,    95, STR_0240_COAL_MINE,             STR_CONSTRUCT_COAL_MINE_TIP},
       
   146 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    97,   108, STR_0243_FOREST,                STR_CONSTRUCT_FOREST_TIP},
       
   147 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   110,   121, STR_0248_FARM,                  STR_CONSTRUCT_FARM_TIP},
       
   148 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   123,   134, STR_024A_OIL_WELLS,             STR_CONSTRUCT_OIL_WELLS_TIP},
       
   149 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   136,   147, STR_024F_GOLD_MINE,             STR_CONSTRUCT_GOLD_MINE_TIP},
       
   150 {   WIDGETS_END},
       
   151 };
       
   152 
       
   153 static const Widget _build_industry_land2_widgets_extra[] = {
       
   154 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
   155 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   156 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   200, 0x0,                            STR_NULL},
       
   157 
       
   158 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0250_LUMBER_MILL,           STR_0273_CONSTRUCT_LUMBER_MILL_TO},
       
   159 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_024D_FOOD_PROCESSING_PLANT, STR_026F_CONSTRUCT_FOOD_PROCESSING},
       
   160 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_0244_OIL_REFINERY,          STR_0266_CONSTRUCT_OIL_REFINERY},
       
   161 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_0246_FACTORY,               STR_0268_CONSTRUCT_FACTORY},
       
   162 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    68,    79, STR_0254_WATER_TOWER,           STR_0277_CONSTRUCT_WATER_TOWER_CAN},
       
   163 
       
   164 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    84,    95, STR_024A_OIL_WELLS,             STR_CONSTRUCT_OIL_WELLS_TIP},
       
   165 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    97,   108, STR_0255_DIAMOND_MINE,          STR_CONSTRUCT_DIAMOND_MINE_TIP},
       
   166 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   110,   121, STR_0256_COPPER_ORE_MINE,       STR_CONSTRUCT_COPPER_ORE_MINE_TIP},
       
   167 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   123,   134, STR_0248_FARM,                  STR_CONSTRUCT_FARM_TIP},
       
   168 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   136,   147, STR_0251_FRUIT_PLANTATION,      STR_CONSTRUCT_FRUIT_PLANTATION_TIP},
       
   169 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   149,   160, STR_0252_RUBBER_PLANTATION,     STR_CONSTRUCT_RUBBER_PLANTATION_TIP},
       
   170 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   162,   173, STR_0253_WATER_SUPPLY,          STR_CONSTRUCT_WATER_SUPPLY_TIP},
       
   171 {   WIDGETS_END},
       
   172 };
       
   173 
       
   174 static const Widget _build_industry_land3_widgets_extra[] = {
       
   175 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
       
   176 {    WWT_CAPTION,   RESIZE_NONE,     7,    11,   169,     0,    13, STR_0314_FUND_NEW_INDUSTRY,     STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   177 {      WWT_PANEL,   RESIZE_NONE,     7,     0,   169,    14,   187, 0x0,                            STR_NULL},
       
   178 
       
   179 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    16,    27, STR_0258_CANDY_FACTORY,         STR_027B_CONSTRUCT_CANDY_FACTORY},
       
   180 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    29,    40, STR_025B_TOY_SHOP,              STR_027E_CONSTRUCT_TOY_SHOP},
       
   181 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    42,    53, STR_025C_TOY_FACTORY,           STR_027F_CONSTRUCT_TOY_FACTORY},
       
   182 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    55,    66, STR_025E_FIZZY_DRINK_FACTORY,   STR_0281_CONSTRUCT_FIZZY_DRINK_FACTORY},
       
   183 
       
   184 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    71,    82, STR_0257_COTTON_CANDY_FOREST,   STR_CONSTRUCT_COTTON_CANDY_TIP},
       
   185 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    84,    95, STR_0259_BATTERY_FARM,          STR_CONSTRUCT_BATTERY_FARM_TIP},
       
   186 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,    97,   108, STR_025A_COLA_WELLS,            STR_CONSTRUCT_COLA_WELLS_TIP},
       
   187 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   110,   121, STR_025D_PLASTIC_FOUNTAINS,     STR_CONSTRUCT_PLASTIC_FOUNTAINS_TIP},
       
   188 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   123,   134, STR_025F_BUBBLE_GENERATOR,      STR_CONSTRUCT_BUBBLE_GENERATOR_TIP},
       
   189 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   136,   147, STR_0260_TOFFEE_QUARRY,         STR_CONSTRUCT_TOFFEE_QUARRY_TIP},
       
   190 {    WWT_TEXTBTN,   RESIZE_NONE,    14,     2,   167,   149,   160, STR_0261_SUGAR_MINE,            STR_CONSTRUCT_SUGAR_MINE_TIP},
       
   191 {   WIDGETS_END},
       
   192 };
       
   193 
       
   194 
       
   195 static const WindowDesc _build_industry_land0_desc = {
       
   196 	WDP_AUTO, WDP_AUTO, 170, 116,
       
   197 	WC_BUILD_INDUSTRY, WC_NONE,
       
   198 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   199 	_build_industry_land0_widgets,
       
   200 	BuildIndustryWndProc
       
   201 };
       
   202 
       
   203 static const WindowDesc _build_industry_land1_desc = {
       
   204 	WDP_AUTO, WDP_AUTO, 170, 116,
       
   205 	WC_BUILD_INDUSTRY, WC_NONE,
       
   206 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   207 	_build_industry_land1_widgets,
       
   208 	BuildIndustryWndProc
       
   209 };
       
   210 
       
   211 static const WindowDesc _build_industry_land2_desc = {
       
   212 	WDP_AUTO, WDP_AUTO, 170, 116,
       
   213 	WC_BUILD_INDUSTRY, WC_NONE,
       
   214 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   215 	_build_industry_land2_widgets,
       
   216 	BuildIndustryWndProc
       
   217 };
       
   218 
       
   219 static const WindowDesc _build_industry_land3_desc = {
       
   220 	WDP_AUTO, WDP_AUTO, 170, 116,
       
   221 	WC_BUILD_INDUSTRY, WC_NONE,
       
   222 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   223 	_build_industry_land3_widgets,
       
   224 	BuildIndustryWndProc
       
   225 };
       
   226 
       
   227 static const WindowDesc _build_industry_land0_desc_extra = {
       
   228 	WDP_AUTO, WDP_AUTO, 170, 188,
       
   229 	WC_BUILD_INDUSTRY, WC_NONE,
       
   230 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   231 	_build_industry_land0_widgets_extra,
       
   232 	BuildIndustryWndProc
       
   233 };
       
   234 
       
   235 static const WindowDesc _build_industry_land1_desc_extra = {
       
   236 	WDP_AUTO, WDP_AUTO, 170, 175,
       
   237 	WC_BUILD_INDUSTRY, WC_NONE,
       
   238 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   239 	_build_industry_land1_widgets_extra,
       
   240 	BuildIndustryWndProc
       
   241 };
       
   242 
       
   243 static const WindowDesc _build_industry_land2_desc_extra = {
       
   244 	WDP_AUTO, WDP_AUTO, 170, 201,
       
   245 	WC_BUILD_INDUSTRY, WC_NONE,
       
   246 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   247 	_build_industry_land2_widgets_extra,
       
   248 	BuildIndustryWndProc
       
   249 };
       
   250 
       
   251 static const WindowDesc _build_industry_land3_desc_extra = {
       
   252 	WDP_AUTO, WDP_AUTO, 170, 188,
       
   253 	WC_BUILD_INDUSTRY, WC_NONE,
       
   254 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   255 	_build_industry_land3_widgets_extra,
       
   256 	BuildIndustryWndProc
       
   257 };
       
   258 
       
   259 static const WindowDesc * const _industry_window_desc[2][4] = {
       
   260 	{
       
   261 	&_build_industry_land0_desc,
       
   262 	&_build_industry_land1_desc,
       
   263 	&_build_industry_land2_desc,
       
   264 	&_build_industry_land3_desc,
       
   265 	},
       
   266 	{
       
   267 	&_build_industry_land0_desc_extra,
       
   268 	&_build_industry_land1_desc_extra,
       
   269 	&_build_industry_land2_desc_extra,
       
   270 	&_build_industry_land3_desc_extra,
       
   271 	},
       
   272 };
       
   273 
       
   274 void ShowBuildIndustryWindow()
   336 void ShowBuildIndustryWindow()
   275 {
   337 {
   276 	if (!IsValidPlayer(_current_player)) return;
   338 	if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return;
   277 	AllocateWindowDescFront(_industry_window_desc[_patches.build_rawmaterial_ind][_opt_ptr->landscape], 0);
   339 	AllocateWindowDescFront(&_build_industry_dynamic_desc, 0);
   278 }
   340 }
       
   341 
       
   342 static void UpdateIndustryProduction(Industry *i);
   279 
   343 
   280 static inline bool isProductionMinimum(const Industry *i, int pt) {
   344 static inline bool isProductionMinimum(const Industry *i, int pt) {
   281 	return i->production_rate[pt] == 1;
   345 	return i->production_rate[pt] == 1;
   282 }
   346 }
   283 
   347 
   297 	/* WP(w,vp2_d).data_1 is for the editbox line
   361 	/* WP(w,vp2_d).data_1 is for the editbox line
   298 	 * WP(w,vp2_d).data_2 is for the clickline
   362 	 * WP(w,vp2_d).data_2 is for the clickline
   299 	 * WP(w,vp2_d).data_3 is for the click pos (left or right) */
   363 	 * WP(w,vp2_d).data_3 is for the click pos (left or right) */
   300 
   364 
   301 	switch (e->event) {
   365 	switch (e->event) {
       
   366 	case WE_CREATE: {
       
   367 		/* Count the number of lines that we need to resize the GUI with */
       
   368 		const IndustrySpec *ind = GetIndustrySpec(GetIndustry(w->window_number)->type);
       
   369 		int lines = -3;
       
   370 
       
   371 		if (HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) {
       
   372 			for (uint j = 0; j < 3 && ind->accepts_cargo[j] != CT_INVALID; j++) {
       
   373 				if (j == 0) lines++;
       
   374 				lines++;
       
   375 			}
       
   376 		} else if (ind->accepts_cargo[0] != CT_INVALID) {
       
   377 			lines++;
       
   378 		}
       
   379 
       
   380 		for (uint j = 0; j < 2 && ind->produced_cargo[j] != CT_INVALID; j++) {
       
   381 			if (j == 0) {
       
   382 				if (ind->accepts_cargo[0] != CT_INVALID) lines++;
       
   383 				lines++;
       
   384 			}
       
   385 			lines++;
       
   386 		}
       
   387 
       
   388 		if (HASBIT(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) lines += 2;
       
   389 
       
   390 		for (uint j = 5; j <= 7; j++) {
       
   391 			if (j != 5) w->widget[j].top += lines * 10;
       
   392 			w->widget[j].bottom += lines * 10;
       
   393 		}
       
   394 		w->height += lines * 10;
       
   395 	} break;
       
   396 
   302 	case WE_PAINT: {
   397 	case WE_PAINT: {
   303 		const Industry *i = GetIndustry(w->window_number);
   398 		Industry *i = GetIndustry(w->window_number);
   304 		const IndustrySpec *ind = GetIndustrySpec(i->type);
   399 		const IndustrySpec *ind = GetIndustrySpec(i->type);
       
   400 		int y = 111;
   305 
   401 
   306 		SetDParam(0, w->window_number);
   402 		SetDParam(0, w->window_number);
   307 		DrawWindowWidgets(w);
   403 		DrawWindowWidgets(w);
   308 
   404 
   309 		if (ind->accepts_cargo[0] != CT_INVALID) {
   405 		if (HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(ind->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) {
       
   406 			for (uint j = 0; j < 3 && ind->accepts_cargo[j] != CT_INVALID; j++) {
       
   407 				if (j == 0) {
       
   408 					DrawString(2, y, STR_INDUSTRY_WINDOW_WAITING_FOR_PROCESSING, 0);
       
   409 					y += 10;
       
   410 				}
       
   411 				SetDParam(0, ind->accepts_cargo[j]);
       
   412 				SetDParam(1, i->incoming_cargo_waiting[j]);
       
   413 				DrawString(4, y, STR_INDUSTRY_WINDOW_WAITING_STOCKPILE_CARGO, 0);
       
   414 				y += 10;
       
   415 			}
       
   416 		} else if (ind->accepts_cargo[0] != CT_INVALID) {
   310 			StringID str;
   417 			StringID str;
   311 
   418 
   312 			SetDParam(0, GetCargo(ind->accepts_cargo[0])->name);
   419 			SetDParam(0, GetCargo(ind->accepts_cargo[0])->name);
   313 			str = STR_4827_REQUIRES;
   420 			str = STR_4827_REQUIRES;
   314 			if (ind->accepts_cargo[1] != CT_INVALID) {
   421 			if (ind->accepts_cargo[1] != CT_INVALID) {
   317 				if (ind->accepts_cargo[2] != CT_INVALID) {
   424 				if (ind->accepts_cargo[2] != CT_INVALID) {
   318 					SetDParam(2, GetCargo(ind->accepts_cargo[2])->name);
   425 					SetDParam(2, GetCargo(ind->accepts_cargo[2])->name);
   319 					str = STR_4829_REQUIRES;
   426 					str = STR_4829_REQUIRES;
   320 				}
   427 				}
   321 			}
   428 			}
   322 			DrawString(2, 107, str, 0);
   429 			DrawString(2, y, str, 0);
   323 		}
   430 			y += 10;
   324 
   431 		}
   325 		if (ind->produced_cargo[0] != CT_INVALID) {
   432 
   326 			DrawString(2, 117, STR_482A_PRODUCTION_LAST_MONTH, 0);
   433 		for (uint j = 0; j < 2 && ind->produced_cargo[j] != CT_INVALID; j++) {
   327 
   434 			if (j == 0) {
   328 			SetDParam(0, ind->produced_cargo[0]);
   435 				if (ind->accepts_cargo[0] != CT_INVALID) y += 10;
   329 			SetDParam(1, i->total_production[0]);
   436 				DrawString(2, y, STR_482A_PRODUCTION_LAST_MONTH, 0);
   330 
   437 				y += 10;
   331 			SetDParam(2, i->pct_transported[0] * 100 >> 8);
   438 			}
   332 			DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), 127, STR_482B_TRANSPORTED, 0);
   439 
       
   440 			SetDParam(0, ind->produced_cargo[j]);
       
   441 			SetDParam(1, i->last_month_production[j]);
       
   442 
       
   443 			SetDParam(2, i->last_month_pct_transported[j] * 100 >> 8);
       
   444 			DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), y, STR_482B_TRANSPORTED, 0);
   333 			/* Let's put out those buttons.. */
   445 			/* Let's put out those buttons.. */
   334 			if (IsProductionAlterable(i)) {
   446 			if (IsProductionAlterable(i)) {
   335 				DrawArrowButtons(5, 127, 3, (WP(w, vp2_d).data_2 == 1) ? WP(w, vp2_d).data_3 : 0,
   447 				DrawArrowButtons(5, y, 3, (WP(w, vp2_d).data_2 == j + 1) ? WP(w, vp2_d).data_3 : 0,
   336 						!isProductionMinimum(i, 0), !isProductionMaximum(i, 0));
   448 						!isProductionMinimum(i, j), !isProductionMaximum(i, j));
   337 			}
   449 			}
   338 
   450 			y += 10;
   339 			if (ind->produced_cargo[1] != CT_INVALID) {
   451 		}
   340 				SetDParam(0, ind->produced_cargo[1]);
   452 
   341 				SetDParam(1, i->total_production[1]);
   453 		/* Get the extra message for the GUI */
   342 				SetDParam(2, i->pct_transported[1] * 100 >> 8);
   454 		if (HASBIT(ind->callback_flags, CBM_IND_WINDOW_MORE_TEXT)) {
   343 				DrawString(4 + (IsProductionAlterable(i) ? 30 : 0), 137, STR_482B_TRANSPORTED, 0);
   455 			uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->xy);
   344 				/* Let's put out those buttons.. */
   456 			if (callback_res != CALLBACK_FAILED) {
   345 				if (IsProductionAlterable(i)) {
   457 				StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res);
   346 					DrawArrowButtons(5, 137, 3, (WP(w, vp2_d).data_2 == 2) ? WP(w, vp2_d).data_3 : 0,
   458 				if (message != STR_NULL && message != STR_UNDEFINED) {
   347 						!isProductionMinimum(i, 1), !isProductionMaximum(i, 1));
   459 					y += 10;
       
   460 					DrawString(2, y, message, 0);
   348 				}
   461 				}
   349 			}
   462 			}
   350 		}
   463 		}
   351 
   464 
   352 		DrawWindowViewport(w);
   465 		DrawWindowViewport(w);
   353 		}
   466 	} break;
   354 		break;
       
   355 
   467 
   356 	case WE_CLICK: {
   468 	case WE_CLICK: {
   357 		Industry *i;
   469 		Industry *i;
   358 
   470 
   359 		switch (e->we.click.widget) {
   471 		switch (e->we.click.widget) {
   364 
   476 
   365 			/* We should work if needed.. */
   477 			/* We should work if needed.. */
   366 			if (!IsProductionAlterable(i)) return;
   478 			if (!IsProductionAlterable(i)) return;
   367 
   479 
   368 			x = e->we.click.pt.x;
   480 			x = e->we.click.pt.x;
   369 			line = (e->we.click.pt.y - 127) / 10;
   481 			line = (e->we.click.pt.y - 121) / 10;
   370 			if (e->we.click.pt.y >= 127 && IS_INT_INSIDE(line, 0, 2) &&
   482 			if (e->we.click.pt.y >= 121 && IS_INT_INSIDE(line, 0, 2) &&
   371 					GetIndustrySpec(i->type)->produced_cargo[line] != CT_INVALID) {
   483 					GetIndustrySpec(i->type)->produced_cargo[line] != CT_INVALID) {
   372 				if (IS_INT_INSIDE(x, 5, 25) ) {
   484 				if (IS_INT_INSIDE(x, 5, 25) ) {
   373 					/* Clicked buttons, decrease or increase production */
   485 					/* Clicked buttons, decrease or increase production */
   374 					if (x < 15) {
   486 					if (x < 15) {
   375 						if (isProductionMinimum(i, line)) return;
   487 						if (isProductionMinimum(i, line)) return;
   421 {
   533 {
   422 	const IndustrySpec *ind = GetIndustrySpec(i->type);
   534 	const IndustrySpec *ind = GetIndustrySpec(i->type);
   423 
   535 
   424 	for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
   536 	for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
   425 		if (ind->produced_cargo[j] != CT_INVALID) {
   537 		if (ind->produced_cargo[j] != CT_INVALID) {
   426 			i->total_production[j] = 8 * i->production_rate[j];
   538 			i->last_month_production[j] = 8 * i->production_rate[j];
   427 		}
   539 		}
   428 	}
   540 	}
   429 }
   541 }
   430 
   542 
   431 static const Widget _industry_view_widgets[] = {
   543 static const Widget _industry_view_widgets[] = {
   507 			} else {
   619 			} else {
   508 				if (ind_j->produced_cargo[0] == CT_INVALID) {
   620 				if (ind_j->produced_cargo[0] == CT_INVALID) {
   509 					r = 1;
   621 					r = 1;
   510 				} else {
   622 				} else {
   511 					r =
   623 					r =
   512 						(i->total_production[0] + i->total_production[1]) -
   624 						(i->last_month_production[0] + i->last_month_production[1]) -
   513 						(j->total_production[0] + j->total_production[1]);
   625 						(j->last_month_production[0] + j->last_month_production[1]);
   514 				}
   626 				}
   515 			}
   627 			}
   516 			break;
   628 			break;
   517 
   629 
   518 		case 3: /* Sort by transported fraction */
   630 		case 3: /* Sort by transported fraction */
   523 					r = 1;
   635 					r = 1;
   524 				} else {
   636 				} else {
   525 					int pi;
   637 					int pi;
   526 					int pj;
   638 					int pj;
   527 
   639 
   528 					pi = i->pct_transported[0] * 100 >> 8;
   640 					pi = i->last_month_pct_transported[0] * 100 >> 8;
   529 					if (ind_i->produced_cargo[1] != CT_INVALID) {
   641 					if (ind_i->produced_cargo[1] != CT_INVALID) {
   530 						int p = i->pct_transported[1] * 100 >> 8;
   642 						int p = i->last_month_pct_transported[1] * 100 >> 8;
   531 						if (p < pi) pi = p;
   643 						if (p < pi) pi = p;
   532 					}
   644 					}
   533 
   645 
   534 					pj = j->pct_transported[0] * 100 >> 8;
   646 					pj = j->last_month_pct_transported[0] * 100 >> 8;
   535 					if (ind_j->produced_cargo[1] != CT_INVALID) {
   647 					if (ind_j->produced_cargo[1] != CT_INVALID) {
   536 						int p = j->pct_transported[1] * 100 >> 8;
   648 						int p = j->last_month_pct_transported[1] * 100 >> 8;
   537 						if (p < pj) pj = p;
   649 						if (p < pj) pj = p;
   538 					}
   650 					}
   539 
   651 
   540 					r = pi - pj;
   652 					r = pi - pj;
   541 				}
   653 				}
   616 			const IndustrySpec *ind = GetIndustrySpec(i->type);
   728 			const IndustrySpec *ind = GetIndustrySpec(i->type);
   617 
   729 
   618 			SetDParam(0, i->index);
   730 			SetDParam(0, i->index);
   619 			if (ind->produced_cargo[0] != CT_INVALID) {
   731 			if (ind->produced_cargo[0] != CT_INVALID) {
   620 				SetDParam(1, ind->produced_cargo[0]);
   732 				SetDParam(1, ind->produced_cargo[0]);
   621 				SetDParam(2, i->total_production[0]);
   733 				SetDParam(2, i->last_month_production[0]);
   622 
   734 
   623 				if (ind->produced_cargo[1] != CT_INVALID) {
   735 				if (ind->produced_cargo[1] != CT_INVALID) {
   624 					SetDParam(3, ind->produced_cargo[1]);
   736 					SetDParam(3, ind->produced_cargo[1]);
   625 					SetDParam(4, i->total_production[1]);
   737 					SetDParam(4, i->last_month_production[1]);
   626 					SetDParam(5, i->pct_transported[0] * 100 >> 8);
   738 					SetDParam(5, i->last_month_pct_transported[0] * 100 >> 8);
   627 					SetDParam(6, i->pct_transported[1] * 100 >> 8);
   739 					SetDParam(6, i->last_month_pct_transported[1] * 100 >> 8);
   628 					DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_TWO, 0);
   740 					DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_TWO, 0);
   629 				} else {
   741 				} else {
   630 					SetDParam(3, i->pct_transported[0] * 100 >> 8);
   742 					SetDParam(3, i->last_month_pct_transported[0] * 100 >> 8);
   631 					DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM, 0);
   743 					DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM, 0);
   632 				}
   744 				}
   633 			} else {
   745 			} else {
   634 				DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_NOPROD, 0);
   746 				DrawString(4, 28 + n * 10, STR_INDUSTRYDIR_ITEM_NOPROD, 0);
   635 			}
   747 			}