src/airport_gui.cpp
branchNewGRF_ports
changeset 10192 195d7f6dcf71
parent 10184 fcf5fb2548eb
child 10242 52b4a9006029
equal deleted inserted replaced
10184:fcf5fb2548eb 10192:195d7f6dcf71
    23 #include "viewport_func.h"
    23 #include "viewport_func.h"
    24 #include "gfx_func.h"
    24 #include "gfx_func.h"
    25 #include "widgets/dropdown_func.h"
    25 #include "widgets/dropdown_func.h"
    26 #include "order_func.h"
    26 #include "order_func.h"
    27 
    27 
    28 //TODO: remove station.h once converted to newgrf airports. stations just used as temporary loader
       
    29 //#include "station.h"
       
    30 
       
    31 #include "table/sprites.h"
    28 #include "table/sprites.h"
    32 #include "table/strings.h"
    29 #include "table/strings.h"
    33 
    30 
    34 static struct {
    31 static struct {
    35 	byte layout_set;
    32 	byte layout_set;
    93 };
    90 };
    94 
    91 
    95 static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
    92 static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
    96 {
    93 {
    97 	switch (e->event) {
    94 	switch (e->event) {
    98 	case WE_PAINT:
    95 		case WE_PAINT:
    99 		DrawWindowWidgets(w);
    96 			DrawWindowWidgets(w);
   100 		break;
    97 			break;
   101 
    98 
   102 	case WE_CLICK:
    99 		case WE_CLICK:
   103 		if (e->we.click.widget - 3 >= 0)
   100 			if (e->we.click.widget - 3 >= 0)
   104 			_build_air_button_proc[e->we.click.widget - 3](w);
   101 				_build_air_button_proc[e->we.click.widget - 3](w);
   105 		break;
   102 			break;
   106 
   103 
   107 	case WE_KEYPRESS: {
   104 		case WE_KEYPRESS: {
   108 		switch (e->we.keypress.keycode) {
   105 			switch (e->we.keypress.keycode) {
   109 			case '1': BuildAirClick_Airport(w); break;
   106 				case '1': BuildAirClick_Airport(w); break;
   110 			case '2': BuildAirClick_Demolish(w); break;
   107 				case '2': BuildAirClick_Demolish(w); break;
   111 			default: return;
   108 				default: return;
       
   109 			}
       
   110 			break;
   112 		}
   111 		}
   113 	} break;
   112 
   114 
   113 		case WE_PLACE_OBJ:
   115 	case WE_PLACE_OBJ:
   114 			_place_proc(e->we.place.tile);
   116 		_place_proc(e->we.place.tile);
   115 			break;
   117 		break;
   116 
   118 
   117 		case WE_PLACE_DRAG:
   119 	case WE_PLACE_DRAG:
   118 			VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
   120 		VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method);
   119 			break;
   121 		break;
   120 
   122 
   121 		case WE_PLACE_MOUSEUP:
   123 	case WE_PLACE_MOUSEUP:
   122 			if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
   124 		if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) {
   123 				DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
   125 			DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
   124 			}
   126 		}
   125 			break;
   127 		break;
   126 
   128 
   127 		case WE_ABORT_PLACE_OBJ:
   129 	case WE_ABORT_PLACE_OBJ:
   128 			w->RaiseButtons();
   130 		w->RaiseButtons();
   129 
   131 
   130 			w = FindWindowById(WC_BUILD_STATION, 0);
   132 		w = FindWindowById(WC_BUILD_STATION, 0);
   131 			if (w != 0)
   133 		if (w != 0)
   132 				WP(w, def_d).close = true;
   134 			WP(w, def_d).close = true;
   133 			break;
   135 		break;
   134 
   136 
   135 		case WE_DESTROY:
   137 	case WE_DESTROY:
   136 			if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
   138 		if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
   137 			break;
   139 		break;
       
   140 	}
   138 	}
   141 }
   139 }
   142 
   140 
   143 static const Widget _air_toolbar_widgets[] = {
   141 static const Widget _air_toolbar_widgets[] = {
   144 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,            STR_018B_CLOSE_WINDOW },
   142 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,            STR_018B_CLOSE_WINDOW },
   189 };
   187 };
   190 
   188 
   191 static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
   189 static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
   192 {
   190 {
   193 	switch (e->event) {
   191 	switch (e->event) {
   194 	case WE_CREATE:
   192 		case WE_CREATE:
   195 		w->SetWidgetLoweredState(BAPW_HIGHLIGHT_OFF, !_station_show_coverage);
   193 			w->SetWidgetLoweredState(BAPW_HIGHLIGHT_OFF, !_station_show_coverage);
   196 		w->SetWidgetLoweredState(BAPW_HIGHLIGHT_ON, _station_show_coverage);
   194 			w->SetWidgetLoweredState(BAPW_HIGHLIGHT_ON, _station_show_coverage);
   197 		break;
   195 			break;
   198 
   196 
   199 	case WE_PAINT: {
   197 		case WE_PAINT: {
   200 		byte preview_sprite = 0xFF;
   198 			byte preview_sprite = 0xFF;
   201 
   199 
   202 		FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type);
   200 			FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type);
   203 		/* if the port is no longer available, find one that is */
   201 			/* if the port is no longer available, find one that is */
   204 		if ((fsmportspec == NULL) || (HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0)) {
   202 			if ((fsmportspec == NULL) || (HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0)) {
   205 			/* port not available, find new one*/
   203 				/* port not available, find new one*/
   206 			_airport.station_type = 0xFF;  //set to the invalid condition to prevent any selection if nothing is available
   204 				_airport.station_type = 0xFF;  //set to the invalid condition to prevent any selection if nothing is available
   207 			for (uint i = 0; i < _airport.station_count; i++) {
   205 				for (uint i = 0; i < _airport.station_count; i++) {
   208 				fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, i);
   206 					fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, i);
       
   207 					if (!HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) || GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) != 0) {
       
   208 						_airport.station_type = i;
       
   209 						break;
       
   210 					}
       
   211 				}
       
   212 			}
       
   213 
       
   214 			if (WP(w, def_d).close) return;
       
   215 
       
   216 			for (byte j = 0; j < 4; j++) {
       
   217 				w->SetWidgetDisabledState(BAPW_ORIENT_NE + j, true);
       
   218 				w->RaiseWidget(BAPW_ORIENT_NE + j);
       
   219 				w->widget[BAPW_ORIENT_NE + j].data = SPR_IMG_ARROW_NE_WHITE + j;  //reset arrows to white
       
   220 			}
       
   221 
       
   222 			if (_airport.station_type != 0xFF) {
       
   223 				int x = fsmportspec->size_x[_airport.layout_set];
       
   224 				int y = fsmportspec->size_y[_airport.layout_set];
       
   225 				SetTileSelectSize(x, y);
       
   226 
       
   227 				/* an airport is available, so read it and update screen accordingly */
       
   228 				for (byte j = 0; j < fsmportspec->numlayouts; j++) {
       
   229 					if (fsmportspec->layouts[j] == NULL) break;
       
   230 					/* enable the permitted orientations */
       
   231 					byte *layout_ptr = (byte*)alloca(x*y + 2);
       
   232 					memcpy(layout_ptr, fsmportspec->layouts[j], (x * y) + 2);
       
   233 					w->SetWidgetDisabledState(BAPW_ORIENT_NE + GB((byte)*layout_ptr, 1, 2), false);
       
   234 					if (j == _airport.layout_set) {
       
   235 						layout_ptr++;
       
   236 						preview_sprite = *layout_ptr;
       
   237 					}
       
   238 				}
       
   239 				w->LowerWidget(BAPW_ORIENT_NE + DirToDiagDir(_airport.direction));
       
   240 				w->widget[BAPW_ORIENT_NE + DirToDiagDir(_airport.direction)].data = SPR_IMG_ARROW_NE_YELLOW + DirToDiagDir(_airport.direction);  //show in yellow
       
   241 			}
       
   242 
       
   243 			SetDParam(0, GetFSMportsClassName(_airport.fsmports_class));
       
   244 			DrawWindowWidgets(w);
       
   245 
       
   246 			/* strings such as 'Size' and 'Coverage Area' */
       
   247 
       
   248 			if (_airport.station_type != 0xFF) {
       
   249 				/* draw the preview image if the station is available */
   209 				if (!HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) || GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) != 0) {
   250 				if (!HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) || GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) != 0) {
   210 					_airport.station_type = i;
   251 					DrawFSMportsTile(9, 106, preview_sprite, _airport.fsmports_class, _airport.station_type);
       
   252 				}
       
   253 				_thd.FSMportLayout = &fsmportspec->layouts[_airport.layout_set];  // irregular airport support
       
   254 				_thd.FSMportMask = NULL;
       
   255 				if (fsmportspec->layout_mask != NULL) _thd.FSMportMask = &fsmportspec->layout_mask[_airport.layout_set];  // irregular airport support
       
   256 				int rad = _patches.modified_catchment ? fsmportspec->portFSM->catchment : 4;
       
   257 				if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
       
   258 				int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad, false);
       
   259 				text_end = DrawStationCoverageAreaText(2, text_end + 4, SCT_ALL, rad, true) + 4;
       
   260 				if (text_end > w->widget[BAPW_BACKGROUND].bottom) {
       
   261 					SetWindowDirty(w);
       
   262 					ResizeWindowForWidget(w, BAPW_BACKGROUND, 0, text_end - w->widget[BAPW_BACKGROUND].bottom);
       
   263 					SetWindowDirty(w);
       
   264 				}
       
   265 			} else {
       
   266 				/* if nothing is selectable, draw the image of the first in the non-selectable list, but grey out the preview */
       
   267 				fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, 0);
       
   268 				byte *layout_ptr = (byte*)alloca(fsmportspec->size_x[0] * fsmportspec->size_y[0] + 2);
       
   269 				memcpy(layout_ptr, fsmportspec->layouts[0], (fsmportspec->size_x[0] * fsmportspec->size_y[0]) + 2);
       
   270 				layout_ptr++;
       
   271 				preview_sprite = *layout_ptr;
       
   272 				DrawFSMportsTile(9, 106, preview_sprite, _airport.fsmports_class, 0);
       
   273 				GfxFillRect(8, 106, 105, 172, (1 << PALETTE_MODIFIER_GREYOUT));
       
   274 				_thd.FSMportLayout = NULL;  // ensure irregular airport support disabled
       
   275 				_thd.FSMportMask = NULL;
       
   276 				SetTileSelectSize(1,1);
       
   277 			}
       
   278 
       
   279 			for (uint16 i = w->vscroll.pos, y = 35; i < _airport.station_count && i < (uint)(w->vscroll.pos + w->vscroll.cap); i++, y += 14) {
       
   280 				const FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, i);
       
   281 
       
   282 				if (fsmportspec != NULL && fsmportspec->name != 0) {
       
   283 					if (HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0) {
       
   284 						GfxFillRect(8, y - 2, 127, y + 10, (1 << PALETTE_MODIFIER_GREYOUT));
       
   285 					}
       
   286 					DrawStringTruncated(9, y, fsmportspec->name, i == _airport.station_type ? 12 : 16, 118);
       
   287 				} else {
       
   288 					DrawStringTruncated(9, y, STR_STAT_CLASS_DFLT, i == _airport.station_type ? 12 : 16, 118);
       
   289 				}
       
   290 			}
       
   291 			break;
       
   292 		}
       
   293 
       
   294 		case WE_CLICK: {
       
   295 			switch (e->we.click.widget) {
       
   296 				case BAPW_HIGHLIGHT_OFF: case BAPW_HIGHLIGHT_ON:
       
   297 					_station_show_coverage = (e->we.click.widget != BAPW_HIGHLIGHT_OFF);
       
   298 					w->SetWidgetLoweredState(BAPW_HIGHLIGHT_OFF, !_station_show_coverage);
       
   299 					w->SetWidgetLoweredState(BAPW_HIGHLIGHT_ON, _station_show_coverage);
       
   300 					SndPlayFx(SND_15_BEEP);
       
   301 					SetWindowDirty(w);
   211 					break;
   302 					break;
   212 				}
   303 				case BAPW_NEWAP_DROPDOWN:
   213 			}
   304 					ShowDropDownList(w, BuildFSMportsClassDropdown(), _airport.fsmports_class, BAPW_NEWAP_DROPDOWN);
       
   305 					break;
       
   306 
       
   307 				case BAPW_NEWAP_LIST: {
       
   308 					const FSMportsSpec *fsmportspec;
       
   309 					int y = (e->we.click.pt.y - 32) / 14;
       
   310 
       
   311 					if (y >= w->vscroll.cap) return;
       
   312 					y += w->vscroll.pos;
       
   313 					if (y >= _airport.station_count) return;
       
   314 
       
   315 					/* Check station availability callback */
       
   316 					fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, y);
       
   317 					if (fsmportspec != NULL &&
       
   318 						HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) &&
       
   319 						GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0) return;
       
   320 
       
   321 					_airport.station_type = y;
       
   322 					_airport.layout_set = 0;
       
   323 					_airport.platlength= fsmportspec->size_y[_airport.layout_set];
       
   324 					_airport.numtracks = fsmportspec->size_x[_airport.layout_set];
       
   325 
       
   326 					SndPlayFx(SND_15_BEEP);
       
   327 					SetWindowDirty(w);
       
   328 					break;
       
   329 				}
       
   330 
       
   331 				case BAPW_ORIENT_NE:
       
   332 				case BAPW_ORIENT_SE:
       
   333 				case BAPW_ORIENT_SW:
       
   334 				case BAPW_ORIENT_NW:
       
   335 					w->widget[BAPW_ORIENT_NE + DirToDiagDir(_airport.direction)].data = SPR_IMG_ARROW_NE_WHITE + DirToDiagDir(_airport.direction);  //reset arrow to white
       
   336 
       
   337 					/* find the layout_set that corresponds to the selected orientation */
       
   338 					FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type);
       
   339 					_airport.layout_set = 0;
       
   340 					_airport.direction = DiagDirToDir((DiagDirection)(e->we.click.widget - BAPW_ORIENT_NE));
       
   341 					for (byte j = 0; j < fsmportspec->numlayouts; j++) {
       
   342 						int x = fsmportspec->size_x[j];
       
   343 						int y = fsmportspec->size_y[j];
       
   344 						if (fsmportspec->layouts[j] == NULL) break;
       
   345 						/* enable the permitted orientations */
       
   346 						byte *layout_ptr = (byte*)alloca(x * y + 2);
       
   347 						memcpy(layout_ptr, fsmportspec->layouts[j], (x * y) + 2);
       
   348 						if (*layout_ptr == _airport.direction) {
       
   349 							_airport.layout_set = j;
       
   350 							break;
       
   351 						}
       
   352 					}
       
   353 
       
   354 					w->SetWidgetLoweredState( BAPW_ORIENT_NE, (_airport.direction == DIR_NE));
       
   355 					w->SetWidgetLoweredState( BAPW_ORIENT_SE, (_airport.direction == DIR_SE));
       
   356 					w->SetWidgetLoweredState( BAPW_ORIENT_SW, (_airport.direction == DIR_SW));
       
   357 					w->SetWidgetLoweredState( BAPW_ORIENT_NW, (_airport.direction == DIR_NW));
       
   358 					SndPlayFx(SND_15_BEEP);
       
   359 					SetWindowDirty(w);
       
   360 					break;
       
   361 			}
       
   362 			break;
   214 		}
   363 		}
   215 
   364 
   216 		if (WP(w, def_d).close) return;
   365 		case WE_DROPDOWN_SELECT: {
   217 
   366 			if (_airport.fsmports_class != e->we.dropdown.index) {
   218 		for (byte j = 0; j < 4; j++) {
   367 				_airport.fsmports_class = (FSMportsClassID)e->we.dropdown.index;
   219 			w->SetWidgetDisabledState(BAPW_ORIENT_NE + j, true);
   368 				_airport.station_type  = 0;
   220 			w->RaiseWidget(BAPW_ORIENT_NE + j);
   369 				_airport.layout_set = 0;
   221 			w->widget[BAPW_ORIENT_NE + j].data = SPR_IMG_ARROW_NE_WHITE + j;  //reset arrows to white
   370 				_airport.direction = DIR_NE;
       
   371 				_airport.station_count = GetNumCustomFSMports(_airport.fsmports_class);
       
   372 
       
   373 				w->vscroll.count = _airport.station_count;
       
   374 				w->vscroll.pos   = _airport.station_type;
       
   375 			}
       
   376 
       
   377 			SndPlayFx(SND_15_BEEP);
       
   378 			SetWindowDirty(w);
       
   379 			break;
   222 		}
   380 		}
   223 
   381 
   224 		if (_airport.station_type != 0xFF) {
   382 
   225 			int x = fsmportspec->size_x[_airport.layout_set];
   383 		case WE_MOUSELOOP: {
   226 			int y = fsmportspec->size_y[_airport.layout_set];
   384 			if (WP(w, def_d).close) {
   227 			SetTileSelectSize(x, y);
   385 				DeleteWindow(w);
   228 
   386 				return;
   229 			/* an airport is available, so read it and update screen accordingly */
   387 			}
   230 			for (byte j = 0; j < fsmportspec->numlayouts; j++) {
   388 
   231 				if (fsmportspec->layouts[j] == NULL) break;
   389 			CheckRedrawStationCoverage(w);
   232 				/* enable the permitted orientations */
   390 			break;
   233 				byte *layout_ptr = (byte*)alloca(x*y + 2);
       
   234 				memcpy(layout_ptr, fsmportspec->layouts[j], (x * y) + 2);
       
   235 				w->SetWidgetDisabledState(BAPW_ORIENT_NE + GB((byte)*layout_ptr, 1, 2), false);
       
   236 				if (j == _airport.layout_set) {
       
   237 					layout_ptr++;
       
   238 					preview_sprite = *layout_ptr;
       
   239 				}
       
   240 			}
       
   241 			w->LowerWidget(BAPW_ORIENT_NE + DirToDiagDir(_airport.direction));
       
   242 			w->widget[BAPW_ORIENT_NE + DirToDiagDir(_airport.direction)].data = SPR_IMG_ARROW_NE_YELLOW + DirToDiagDir(_airport.direction);  //show in yellow
       
   243 		}
   391 		}
   244 
   392 
   245 		SetDParam(0, GetFSMportsClassName(_airport.fsmports_class));
   393 		case WE_DESTROY:
   246 		DrawWindowWidgets(w);
   394 			if (!WP(w, def_d).close) ResetObjectToPlace();
   247 
       
   248 		// strings such as 'Size' and 'Coverage Area'
       
   249 		// 'Coverage Area'
       
   250 		if (_airport.station_type != 0xFF) {
       
   251 			/* draw the preview image if the station is available */
       
   252 			if (!HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) || GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) != 0) {
       
   253 				DrawFSMportsTile(9, 106, preview_sprite, _airport.fsmports_class, _airport.station_type);
       
   254 			}
       
   255 			_thd.FSMportLayout = &fsmportspec->layouts[_airport.layout_set];  // irregular airport support
       
   256 			_thd.FSMportMask = NULL;
       
   257 			if (fsmportspec->layout_mask != NULL) _thd.FSMportMask = &fsmportspec->layout_mask[_airport.layout_set];  // irregular airport support
       
   258 			int rad = _patches.modified_catchment ? fsmportspec->portFSM->catchment : 4;
       
   259 			if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
       
   260 			int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad, false);
       
   261 			text_end = DrawStationCoverageAreaText(2, text_end + 4, SCT_ALL, rad, true) + 4;
       
   262 			if (text_end > w->widget[BAPW_BACKGROUND].bottom) {
       
   263 				SetWindowDirty(w);
       
   264 				ResizeWindowForWidget(w, BAPW_BACKGROUND, 0, text_end - w->widget[BAPW_BACKGROUND].bottom);
       
   265 				SetWindowDirty(w);
       
   266 			}
       
   267 		} else {
       
   268 			/* if nothing is selectable, draw the image of the first in the non-selectable list, but grey out the preview */
       
   269 			fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, 0);
       
   270 			byte *layout_ptr = (byte*)alloca(fsmportspec->size_x[0] * fsmportspec->size_y[0] + 2);
       
   271 			memcpy(layout_ptr, fsmportspec->layouts[0], (fsmportspec->size_x[0] * fsmportspec->size_y[0]) + 2);
       
   272 			layout_ptr++;
       
   273 			preview_sprite = *layout_ptr;
       
   274 			DrawFSMportsTile(9, 106, preview_sprite, _airport.fsmports_class, 0);
       
   275 			GfxFillRect(8, 106, 105, 172, (1 << PALETTE_MODIFIER_GREYOUT));
       
   276 			_thd.FSMportLayout = NULL;  // ensure irregular airport support disabled
   395 			_thd.FSMportLayout = NULL;  // ensure irregular airport support disabled
   277 			_thd.FSMportMask = NULL;
   396 			_thd.FSMportMask = NULL;
   278 			SetTileSelectSize(1,1);
   397 			break;
   279 		}
       
   280 
       
   281 		for (uint16 i = w->vscroll.pos, y = 35; i < _airport.station_count && i < (uint)(w->vscroll.pos + w->vscroll.cap); i++, y += 14) {
       
   282 			const FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, i);
       
   283 
       
   284 			if (fsmportspec != NULL && fsmportspec->name != 0) {
       
   285 				if (HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0) {
       
   286 					GfxFillRect(8, y - 2, 127, y + 10, (1 << PALETTE_MODIFIER_GREYOUT));
       
   287 				}
       
   288 				DrawStringTruncated(9, y, fsmportspec->name, i == _airport.station_type ? 12 : 16, 118);
       
   289 			} else {
       
   290 				DrawStringTruncated(9, y, STR_STAT_CLASS_DFLT, i == _airport.station_type ? 12 : 16, 118);
       
   291 			}
       
   292 		}
       
   293 		break;
       
   294 	}
       
   295 
       
   296 	case WE_CLICK: {
       
   297 		switch (e->we.click.widget) {
       
   298 		case BAPW_HIGHLIGHT_OFF: case BAPW_HIGHLIGHT_ON:
       
   299 			_station_show_coverage = (e->we.click.widget != BAPW_HIGHLIGHT_OFF);
       
   300 			w->SetWidgetLoweredState(BAPW_HIGHLIGHT_OFF, !_station_show_coverage);
       
   301 			w->SetWidgetLoweredState(BAPW_HIGHLIGHT_ON, _station_show_coverage);
       
   302 			SndPlayFx(SND_15_BEEP);
       
   303 			SetWindowDirty(w);
       
   304 			break;
       
   305 		case BAPW_NEWAP_DROPDOWN:
       
   306 			ShowDropDownList(w, BuildFSMportsClassDropdown(), _airport.fsmports_class, BAPW_NEWAP_DROPDOWN);
       
   307 			break;
       
   308 
       
   309 		case BAPW_NEWAP_LIST: {
       
   310 			const FSMportsSpec *fsmportspec;
       
   311 			int y = (e->we.click.pt.y - 32) / 14;
       
   312 
       
   313 			if (y >= w->vscroll.cap) return;
       
   314 			y += w->vscroll.pos;
       
   315 			if (y >= _airport.station_count) return;
       
   316 
       
   317 			/* Check station availability callback */
       
   318 			fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, y);
       
   319 			if (fsmportspec != NULL &&
       
   320 				HasBit(fsmportspec->callbackmask, CBM_STATION_AVAIL) &&
       
   321 				GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportspec, NULL, INVALID_TILE) == 0) return;
       
   322 
       
   323 			_airport.station_type = y;
       
   324 			_airport.layout_set = 0;
       
   325 			_airport.platlength= fsmportspec->size_y[_airport.layout_set];
       
   326 			_airport.numtracks = fsmportspec->size_x[_airport.layout_set];
       
   327 
       
   328 			SndPlayFx(SND_15_BEEP);
       
   329 			SetWindowDirty(w);
       
   330 			break;
       
   331 			}
       
   332 		case BAPW_ORIENT_NE:
       
   333 		case BAPW_ORIENT_SE:
       
   334 		case BAPW_ORIENT_SW:
       
   335 		case BAPW_ORIENT_NW:
       
   336 			w->widget[BAPW_ORIENT_NE + DirToDiagDir(_airport.direction)].data = SPR_IMG_ARROW_NE_WHITE + DirToDiagDir(_airport.direction);  //reset arrow to white
       
   337 
       
   338 			/* find the layout_set that corresponds to the selected orientation */
       
   339 			FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type);
       
   340 			_airport.layout_set = 0;
       
   341 			_airport.direction = DiagDirToDir((DiagDirection)(e->we.click.widget - BAPW_ORIENT_NE));
       
   342 			for (byte j = 0; j < fsmportspec->numlayouts; j++) {
       
   343 				int x = fsmportspec->size_x[j];
       
   344 				int y = fsmportspec->size_y[j];
       
   345 				if (fsmportspec->layouts[j] == NULL) break;
       
   346 				/* enable the permitted orientations */
       
   347 				byte *layout_ptr = (byte*)alloca(x * y + 2);
       
   348 				memcpy(layout_ptr, fsmportspec->layouts[j], (x * y) + 2);
       
   349 				if (*layout_ptr == _airport.direction) {
       
   350 					_airport.layout_set = j;
       
   351 					break;
       
   352 				}
       
   353 			}
       
   354 
       
   355 			w->SetWidgetLoweredState( BAPW_ORIENT_NE, (_airport.direction == DIR_NE));
       
   356 			w->SetWidgetLoweredState( BAPW_ORIENT_SE, (_airport.direction == DIR_SE));
       
   357 			w->SetWidgetLoweredState( BAPW_ORIENT_SW, (_airport.direction == DIR_SW));
       
   358 			w->SetWidgetLoweredState( BAPW_ORIENT_NW, (_airport.direction == DIR_NW));
       
   359 			SndPlayFx(SND_15_BEEP);
       
   360 			SetWindowDirty(w);
       
   361 			break;
       
   362 		}
       
   363 	} break;
       
   364 
       
   365 	case WE_DROPDOWN_SELECT: {
       
   366 		if (_airport.fsmports_class != e->we.dropdown.index) {
       
   367 			_airport.fsmports_class = (FSMportsClassID)e->we.dropdown.index;
       
   368 			_airport.station_type  = 0;
       
   369 			_airport.layout_set = 0;
       
   370 			_airport.direction = DIR_NE;
       
   371 			_airport.station_count = GetNumCustomFSMports(_airport.fsmports_class);
       
   372 
       
   373 			w->vscroll.count = _airport.station_count;
       
   374 			w->vscroll.pos   = _airport.station_type;
       
   375 		}
       
   376 
       
   377 		SndPlayFx(SND_15_BEEP);
       
   378 		SetWindowDirty(w);
       
   379 	} break;
       
   380 
       
   381 
       
   382 	case WE_MOUSELOOP: {
       
   383 		if (WP(w, def_d).close) {
       
   384 			DeleteWindow(w);
       
   385 			return;
       
   386 		}
       
   387 
       
   388 		CheckRedrawStationCoverage(w);
       
   389 	} break;
       
   390 
       
   391 	case WE_DESTROY:
       
   392 		if (!WP(w, def_d).close) ResetObjectToPlace();
       
   393 		_thd.FSMportLayout = NULL;  // ensure irregular airport support disabled
       
   394 		_thd.FSMportMask = NULL;
       
   395 		break;
       
   396 	}
   398 	}
   397 }
   399 }
   398 
   400 
   399 static const Widget _build_airport_picker_widgets[] = {
   401 static const Widget _build_airport_picker_widgets[] = {
   400 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},
   402 {   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},