src/toolbar_gui.cpp
changeset 8975 678648173fcf
parent 8969 6d1c74e0e2cd
child 8977 288be89be1dc
--- a/src/toolbar_gui.cpp	Fri Apr 18 10:58:11 2008 +0000
+++ b/src/toolbar_gui.cpp	Fri Apr 18 15:11:39 2008 +0000
@@ -29,22 +29,42 @@
 #include "vehicle_base.h"
 #include "gfx_func.h"
 #include "cheat_func.h"
+#include "transparency_gui.h"
+#include "screenshot.h"
+#include "newgrf_config.h"
+#include "signs_func.h"
+#include "fios.h"
+#include "functions.h"
+#include "console.h"
 
 #include "network/network.h"
+#include "network/network_gui.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
 
-extern void SelectSignTool();
-extern RailType _last_built_railtype;
-extern RoadType _last_built_roadtype;
+static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask);
+static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray);
 
-/* Returns the position where the toolbar wants the menu to appear.
+RailType _last_built_railtype;
+RoadType _last_built_roadtype;
+
+static void SelectSignTool()
+{
+	if (_cursor.sprite == SPR_CURSOR_SIGN) {
+		ResetObjectToPlace();
+	} else {
+		SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, VHM_RECT, WC_MAIN_TOOLBAR, 0);
+		_place_proc = PlaceProc_Sign;
+	}
+}
+
+/** Returns the position where the toolbar wants the menu to appear.
  * Make sure the dropdown is fully visible within the window.
  * x + w->left because x is supposed to be the offset of the toolbar-button
  * we clicked on and w->left the toolbar window itself. So meaning that
  * the default position is aligned with the left side of the clicked button */
-Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
+static Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
 {
 	const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
 	Point pos;
@@ -55,6 +75,7 @@
 	return pos;
 }
 
+/* --- Pausing --- */
 
 static void ToolbarPauseClick(Window *w)
 {
@@ -63,168 +84,15 @@
 	if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
 }
 
+/* --- Fast forwarding --- */
+
 static void ToolbarFastForwardClick(Window *w)
 {
 	_fast_forward ^= true;
 	SndPlayFx(SND_15_BEEP);
 }
 
-static void ToolbarSaveClick(Window *w)
-{
-	PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
-}
-
-static void ToolbarMapClick(Window *w)
-{
-	PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
-}
-
-static void ToolbarTownClick(Window *w)
-{
-	PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
-}
-
-static void ToolbarSubsidiesClick(Window *w)
-{
-	PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
-}
-
-static void ToolbarStationsClick(Window *w)
-{
-	PopupMainPlayerToolbMenu(w, 7, 0);
-}
-
-static void ToolbarMoneyClick(Window *w)
-{
-	PopupMainPlayerToolbMenu(w, 8, 0);
-}
-
-static void ToolbarPlayersClick(Window *w)
-{
-	PopupMainPlayerToolbMenu(w, 9, 0);
-}
-
-static void ToolbarGraphsClick(Window *w)
-{
-	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
-}
-
-static void ToolbarLeagueClick(Window *w)
-{
-	PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
-}
-
-static void ToolbarIndustryClick(Window *w)
-{
-	/* Disable build-industry menu if we are a spectator */
-	PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
-}
-
-static void ToolbarTrainClick(Window *w)
-{
-	const Vehicle *v;
-	int dis = -1;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner);
-	}
-	PopupMainPlayerToolbMenu(w, 13, dis);
-}
-
-static void ToolbarRoadClick(Window *w)
-{
-	const Vehicle *v;
-	int dis = -1;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner);
-	}
-	PopupMainPlayerToolbMenu(w, 14, dis);
-}
-
-static void ToolbarShipClick(Window *w)
-{
-	const Vehicle *v;
-	int dis = -1;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_SHIP) ClrBit(dis, v->owner);
-	}
-	PopupMainPlayerToolbMenu(w, 15, dis);
-}
-
-static void ToolbarAirClick(Window *w)
-{
-	const Vehicle *v;
-	int dis = -1;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner);
-	}
-	PopupMainPlayerToolbMenu(w, 16, dis);
-}
-
-
-static void ToolbarZoomInClick(Window *w)
-{
-	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
-		w->HandleButtonClick(17);
-		SndPlayFx(SND_15_BEEP);
-	}
-}
-
-static void ToolbarZoomOutClick(Window *w)
-{
-	if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
-		w->HandleButtonClick(18);
-		SndPlayFx(SND_15_BEEP);
-	}
-}
-
-static void ToolbarBuildRailClick(Window *w)
-{
-	const Player *p = GetPlayer(_local_player);
-	Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
-	WP(w2, menu_d).sel_index = _last_built_railtype;
-}
-
-static void ToolbarBuildRoadClick(Window *w)
-{
-	const Player *p = GetPlayer(_local_player);
-	/* The standard road button is *always* available */
-	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
-	WP(w2, menu_d).sel_index = _last_built_roadtype;
-}
-
-static void ToolbarBuildWaterClick(Window *w)
-{
-	PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
-}
-
-static void ToolbarBuildAirClick(Window *w)
-{
-	PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
-}
-
-static void ToolbarForestClick(Window *w)
-{
-	PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
-}
-
-static void ToolbarMusicClick(Window *w)
-{
-	PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
-}
-
-static void ToolbarNewspaperClick(Window *w)
-{
-	PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
-}
-
-static void ToolbarHelpClick(Window *w)
-{
-	PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
-}
+/* --- Options button menu --- */
 
 static void ToolbarOptionsClick(Window *w)
 {
@@ -243,12 +111,412 @@
 	WP(w, menu_d).checked_items = x;
 }
 
+static void MenuClickSettings(int index)
+{
+	switch (index) {
+		case 0: ShowGameOptions();      return;
+		case 1: ShowGameDifficulty();   return;
+		case 2: ShowPatchesSelection(); return;
+		case 3: ShowNewGRFSettings(!_networking, true, true, &_grfconfig);   return;
+		case 4: ShowTransparencyToolbar(); break;
+
+		case  6: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES);    break;
+		case  7: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
+		case  8: ToggleBit(_display_opt, DO_SHOW_SIGNS);         break;
+		case  9: ToggleBit(_display_opt, DO_WAYPOINTS);          break;
+		case 10: ToggleBit(_display_opt, DO_FULL_ANIMATION);     break;
+		case 11: ToggleBit(_display_opt, DO_FULL_DETAIL);        break;
+		case 12: ToggleTransparency(TO_HOUSES);                  break;
+		case 13: ToggleTransparency(TO_SIGNS);                   break;
+	}
+	MarkWholeScreenDirty();
+}
+
+/* --- Saving/loading button menu --- */
+
+static void ToolbarSaveClick(Window *w)
+{
+	PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
+}
 
 static void ToolbarScenSaveOrLoad(Window *w)
 {
 	PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
 }
 
+static void MenuClickSaveLoad(int index)
+{
+	if (_game_mode == GM_EDITOR) {
+		switch (index) {
+			case 0: ShowSaveLoadDialog(SLD_SAVE_SCENARIO);  break;
+			case 1: ShowSaveLoadDialog(SLD_LOAD_SCENARIO);  break;
+			case 2: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
+			case 3: AskExitToGameMenu();                    break;
+			case 5: HandleExitGameRequest();                break;
+		}
+	} else {
+		switch (index) {
+			case 0: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
+			case 1: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
+			case 2: AskExitToGameMenu();               break;
+			case 3: HandleExitGameRequest();           break;
+		}
+	}
+}
+
+/* --- Map button menu --- */
+
+static void ToolbarMapClick(Window *w)
+{
+	PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
+}
+
+static void MenuClickMap(int index)
+{
+	switch (index) {
+		case 0: ShowSmallMap();            break;
+		case 1: ShowExtraViewPortWindow(); break;
+		case 2: ShowSignList();            break;
+	}
+}
+
+static void MenuClickScenMap(int index)
+{
+	switch (index) {
+		case 0: ShowSmallMap();            break;
+		case 1: ShowExtraViewPortWindow(); break;
+		case 2: ShowSignList();            break;
+		case 3: ShowTownDirectory();       break;
+	}
+}
+
+/* --- Town button menu --- */
+
+static void ToolbarTownClick(Window *w)
+{
+	PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
+}
+
+static void MenuClickTown(int index)
+{
+	ShowTownDirectory();
+}
+
+/* --- Subidies button menu --- */
+
+static void ToolbarSubsidiesClick(Window *w)
+{
+	PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
+}
+
+static void MenuClickSubsidies(int index)
+{
+	ShowSubsidiesList();
+}
+
+/* --- Stations button menu --- */
+
+static void ToolbarStationsClick(Window *w)
+{
+	PopupMainPlayerToolbMenu(w, 7, 0);
+}
+
+static void MenuClickStations(int index)
+{
+	ShowPlayerStations((PlayerID)index);
+}
+
+/* --- Finances button menu --- */
+
+static void ToolbarFinancesClick(Window *w)
+{
+	PopupMainPlayerToolbMenu(w, 8, 0);
+}
+
+static void MenuClickFinances(int index)
+{
+	ShowPlayerFinances((PlayerID)index);
+}
+
+/* --- Company's button menu --- */
+
+static void ToolbarPlayersClick(Window *w)
+{
+	PopupMainPlayerToolbMenu(w, 9, 0);
+}
+
+static void MenuClickCompany(int index)
+{
+	if (_networking && index == 0) {
+		ShowClientList();
+	} else {
+		if (_networking) index--;
+		ShowPlayerCompany((PlayerID)index);
+	}
+}
+
+/* --- Graphs button menu --- */
+
+static void ToolbarGraphsClick(Window *w)
+{
+	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
+}
+
+static void MenuClickGraphs(int index)
+{
+	switch (index) {
+		case 0: ShowOperatingProfitGraph();    break;
+		case 1: ShowIncomeGraph();             break;
+		case 2: ShowDeliveredCargoGraph();     break;
+		case 3: ShowPerformanceHistoryGraph(); break;
+		case 4: ShowCompanyValueGraph();       break;
+		case 5: ShowCargoPaymentRates();       break;
+	}
+}
+
+/* --- League button menu --- */
+
+static void ToolbarLeagueClick(Window *w)
+{
+	PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
+}
+
+static void MenuClickLeague(int index)
+{
+	switch (index) {
+		case 0: ShowCompanyLeagueTable();      break;
+		case 1: ShowPerformanceRatingDetail(); break;
+	}
+}
+
+/* --- Industries button menu --- */
+
+static void ToolbarIndustryClick(Window *w)
+{
+	/* Disable build-industry menu if we are a spectator */
+	PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
+}
+
+static void MenuClickIndustry(int index)
+{
+	switch (index) {
+		case 0: ShowIndustryDirectory();   break;
+		case 1: ShowBuildIndustryWindow(); break;
+	}
+}
+
+/* --- Trains button menu + 1 helper function for all vehicles. --- */
+
+static void ToolbarVehicleClick(Window *w, VehicleType veh)
+{
+	const Vehicle *v;
+	int dis = ~0;
+
+	FOR_ALL_VEHICLES(v) {
+		if (v->type == veh && v->IsPrimaryVehicle()) {
+			ClrBit(dis, v->owner);
+			break;
+		}
+	}
+	PopupMainPlayerToolbMenu(w, 13 + veh, dis);
+}
+
+
+static void ToolbarTrainClick(Window *w)
+{
+	ToolbarVehicleClick(w, VEH_TRAIN);
+}
+
+static void MenuClickShowTrains(int index)
+{
+	ShowVehicleListWindow((PlayerID)index, VEH_TRAIN);
+}
+
+/* --- Road vehicle button menu --- */
+
+static void ToolbarRoadClick(Window *w)
+{
+	ToolbarVehicleClick(w, VEH_ROAD);
+}
+
+static void MenuClickShowRoad(int index)
+{
+	ShowVehicleListWindow((PlayerID)index, VEH_ROAD);
+}
+
+/* --- Ship button menu --- */
+
+static void ToolbarShipClick(Window *w)
+{
+	ToolbarVehicleClick(w, VEH_SHIP);
+}
+
+static void MenuClickShowShips(int index)
+{
+	ShowVehicleListWindow((PlayerID)index, VEH_SHIP);
+}
+
+/* --- Aircraft button menu --- */
+
+static void ToolbarAirClick(Window *w)
+{
+	ToolbarVehicleClick(w, VEH_AIRCRAFT);
+}
+
+static void MenuClickShowAir(int index)
+{
+	ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT);
+}
+
+/* --- Zoom in button --- */
+
+static void ToolbarZoomInClick(Window *w)
+{
+	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
+		w->HandleButtonClick(17);
+		SndPlayFx(SND_15_BEEP);
+	}
+}
+
+/* --- Zoom out button --- */
+
+static void ToolbarZoomOutClick(Window *w)
+{
+	if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
+		w->HandleButtonClick(18);
+		SndPlayFx(SND_15_BEEP);
+	}
+}
+
+/* --- Rail button menu --- */
+
+static void ToolbarBuildRailClick(Window *w)
+{
+	const Player *p = GetPlayer(_local_player);
+	Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
+	WP(w2, menu_d).sel_index = _last_built_railtype;
+}
+
+static void MenuClickBuildRail(int index)
+{
+	_last_built_railtype = (RailType)index;
+	ShowBuildRailToolbar(_last_built_railtype, -1);
+}
+
+/* --- Road button menu --- */
+
+static void ToolbarBuildRoadClick(Window *w)
+{
+	const Player *p = GetPlayer(_local_player);
+	/* The standard road button is *always* available */
+	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
+	WP(w2, menu_d).sel_index = _last_built_roadtype;
+}
+
+static void MenuClickBuildRoad(int index)
+{
+	_last_built_roadtype = (RoadType)index;
+	ShowBuildRoadToolbar(_last_built_roadtype);
+}
+
+/* --- Water button menu --- */
+
+static void ToolbarBuildWaterClick(Window *w)
+{
+	PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
+}
+
+static void MenuClickBuildWater(int index)
+{
+	ShowBuildDocksToolbar();
+}
+
+/* --- Airport button menu --- */
+
+static void ToolbarBuildAirClick(Window *w)
+{
+	PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
+}
+
+static void MenuClickBuildAir(int index)
+{
+	ShowBuildAirToolbar();
+}
+
+/* --- Forest button menu --- */
+
+static void ToolbarForestClick(Window *w)
+{
+	PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
+}
+
+static void MenuClickForest(int index)
+{
+	switch (index) {
+		case 0: ShowTerraformToolbar();  break;
+		case 1: ShowBuildTreesToolbar(); break;
+		case 2: SelectSignTool();        break;
+	}
+}
+
+/* --- Music button menu --- */
+
+static void ToolbarMusicClick(Window *w)
+{
+	PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
+}
+
+static void MenuClickMusicWindow(int index)
+{
+	ShowMusicWindow();
+}
+
+/* --- Newspaper button menu --- */
+
+static void ToolbarNewspaperClick(Window *w)
+{
+	PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
+}
+
+static void MenuClickNewspaper(int index)
+{
+	switch (index) {
+		case 0: ShowLastNewsMessage(); break;
+		case 1: ShowMessageOptions();  break;
+		case 2: ShowMessageHistory();  break;
+	}
+}
+
+/* --- Help button menu --- */
+
+static void ToolbarHelpClick(Window *w)
+{
+	PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
+}
+
+static void MenuClickSmallScreenshot()
+{
+	SetScreenshotType(SC_VIEWPORT);
+}
+
+static void MenuClickWorldScreenshot()
+{
+	SetScreenshotType(SC_WORLD);
+}
+
+static void MenuClickHelp(int index)
+{
+	switch (index) {
+		case 0: PlaceLandBlockInfo();       break;
+		case 2: IConsoleSwitch();           break;
+		case 3: MenuClickSmallScreenshot(); break;
+		case 4: MenuClickWorldScreenshot(); break;
+		case 5: ShowAboutWindow();          break;
+	}
+}
+
+/* --- Scenario editor specific handlers. */
+
 static void ToolbarScenDateBackward(Window *w)
 {
 	/* don't allow too fast scrolling */
@@ -346,6 +614,8 @@
 }
 
 
+/* --- Toolbar handling for the 'normal' case */
+
 typedef void ToolbarButtonProc(Window *w);
 
 static ToolbarButtonProc * const _toolbar_button_procs[] = {
@@ -357,7 +627,7 @@
 	ToolbarTownClick,
 	ToolbarSubsidiesClick,
 	ToolbarStationsClick,
-	ToolbarMoneyClick,
+	ToolbarFinancesClick,
 	ToolbarPlayersClick,
 	ToolbarGraphsClick,
 	ToolbarLeagueClick,
@@ -378,11 +648,7 @@
 	ToolbarHelpClick,
 };
 
-extern void MenuClickSmallScreenshot();
-extern void MenuClickWorldScreenshot();
-extern void MenuClickSaveLoad(int index);
-
-void MainToolbarWndProc(Window *w, WindowEvent *e)
+static void MainToolbarWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
 		case WE_PAINT:
@@ -404,8 +670,7 @@
 			break;
 
 		case WE_CLICK:
-			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget))
-				_toolbar_button_procs[e->we.click.widget](w);
+			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) _toolbar_button_procs[e->we.click.widget](w);
 			break;
 
 		case WE_KEYPRESS:
@@ -561,6 +826,8 @@
 };
 
 
+/* --- Toolbar handling for the scenario editor */
+
 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
 	ToolbarPauseClick,
 	ToolbarFastForwardClick,
@@ -591,7 +858,7 @@
 	ToolbarHelpClick,
 };
 
-void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
+static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
 		case WE_PAINT:
@@ -794,7 +1061,375 @@
 	ScenEditToolbarWndProc
 };
 
+/* --- Rendering/handling the drop down menus --- */
+
+typedef void MenuClickedProc(int index);
+
+static MenuClickedProc * const _menu_clicked_procs[] = {
+	NULL,                 /* 0 */
+	NULL,                 /* 1 */
+	MenuClickSettings,    /* 2 */
+	MenuClickSaveLoad,    /* 3 */
+	MenuClickMap,         /* 4 */
+	MenuClickTown,        /* 5 */
+	MenuClickSubsidies,   /* 6 */
+	MenuClickStations,    /* 7 */
+	MenuClickFinances,    /* 8 */
+	MenuClickCompany,     /* 9 */
+	MenuClickGraphs,      /* 10 */
+	MenuClickLeague,      /* 11 */
+	MenuClickIndustry,    /* 12 */
+	MenuClickShowTrains,  /* 13 */
+	MenuClickShowRoad,    /* 14 */
+	MenuClickShowShips,   /* 15 */
+	MenuClickShowAir,     /* 16 */
+	MenuClickScenMap,     /* 17 */
+	NULL,                 /* 18 */
+	MenuClickBuildRail,   /* 19 */
+	MenuClickBuildRoad,   /* 20 */
+	MenuClickBuildWater,  /* 21 */
+	MenuClickBuildAir,    /* 22 */
+	MenuClickForest,      /* 23 */
+	MenuClickMusicWindow, /* 24 */
+	MenuClickNewspaper,   /* 25 */
+	MenuClickHelp,        /* 26 */
+};
+
+static void MenuWndProc(Window *w, WindowEvent *e)
+{
+	switch (e->event) {
+		case WE_CREATE:
+			w->widget[0].right = w->width - 1;
+			break;
+
+		case WE_PAINT: {
+			byte count = WP(w, menu_d).item_count;
+			byte sel = WP(w, menu_d).sel_index;
+			uint16 chk = WP(w, menu_d).checked_items;
+			StringID string = WP(w, menu_d).string_id;
+			byte dis = WP(w, menu_d).disabled_items;
+
+			DrawWindowWidgets(w);
+
+			int x = 1;
+			int y = 1;
+
+			for (; count != 0; count--, string++, sel--) {
+				TextColour color = HasBit(dis, 0) ? TC_GREY : (sel == 0) ? TC_WHITE : TC_BLACK;
+				if (sel == 0) GfxFillRect(x, y, x + w->width - 3, y + 9, 0);
+
+				if (HasBit(chk, 0)) DrawString(x + 2, y, STR_CHECKMARK, color);
+				DrawString(x + 2, y, string, color);
+
+				y += 10;
+				chk >>= 1;
+				dis >>= 1;
+			}
+		} break;
+
+		case WE_DESTROY: {
+				Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
+				v->RaiseWidget(WP(w, menu_d).main_button);
+				SetWindowDirty(v);
+				return;
+			}
+
+		case WE_POPUPMENU_SELECT: {
+			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
+
+			if (index < 0) {
+				Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
+				if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
+					index = WP(w, menu_d).sel_index;
+			}
+
+			int action_id = WP(w, menu_d).action_id;
+			DeleteWindow(w);
+
+			if (index >= 0) {
+				assert((uint)index <= lengthof(_menu_clicked_procs));
+				_menu_clicked_procs[action_id](index);
+			}
+
+		} break;
+
+		case WE_POPUPMENU_OVER: {
+			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
+
+			if (index == -1 || index == WP(w, menu_d).sel_index) return;
+
+			WP(w, menu_d).sel_index = index;
+			SetWindowDirty(w);
+			return;
+		}
+	}
+}
+
+/* Dynamic widget length determined by toolbar-string length.
+ * See PopupMainToolbMenu en MenuWndProc */
+static const Widget _menu_widgets[] = {
+{    WWT_PANEL, RESIZE_NONE, 14, 0,  0, 0, 0, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
+
+
+/**
+ * Get the maximum length of a given string in a string-list. This is an
+ * implicit string-list where the ID's are consecutive
+ * @param base_string StringID of the first string in the list
+ * @param count amount of StringID's in the list
+ * @return the length of the longest string
+ */
+static int GetStringListMaxWidth(StringID base_string, byte count)
+{
+	char buffer[512];
+	int width, max_width = 0;
+
+	for (byte i = 0; i != count; i++) {
+		GetString(buffer, base_string + i, lastof(buffer));
+		width = GetStringBoundingBox(buffer).width;
+		if (width > max_width) max_width = width;
+	}
+
+	return max_width;
+}
+
+/**
+ * Show a general dropdown menu. The positioning of the dropdown menu
+ * defaults to the left side of the parent_button, eg the button that caused
+ * this window to appear. The only exceptions are when the right side of this
+ * dropdown would fall outside the main toolbar window, in that case it is
+ * aligned with the toolbar's right side.
+ * Since the disable-mask is only 8 bits right now, these dropdowns are
+ * restricted to 8 items max if any bits of disabled_mask are active.
+ * @param w Pointer to a window this dropdown menu belongs to. Has no effect
+ * whatsoever, only graphically for positioning.
+ * @param parent_button The widget identifier of the button that was clicked for
+ * this dropdown. The created dropdown then knows what button to raise (button) on
+ * action and whose function to execute (action).
+ * It is possible to appoint another button for an action event by setting the
+ * upper 8 bits of this parameter. If non is set, action is presumed to be the same
+ * as button. So<br>
+ * button bits 0 -  7 - widget clicked to get dropdown
+ * action bits 8 - 15 - function of widget to execute on select (defaults to bits 0 - 7)
+ * @param base_string The first StringID shown in the dropdown list. All others are
+ * consecutive indeces from the language file. XXX - fix? Use ingame-string tables?
+ * @param item_count Number of strings in the list, see previous parameter
+ * @param disabled_mask Bitmask of disabled strings in the list
+ * @return Return a pointer to the newly created dropdown window */
+static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask)
+{
+	assert(disabled_mask == 0 || item_count <= 8);
+	w->LowerWidget(parent_button);
+	w->InvalidateWidget(parent_button);
+
+	DeleteWindowById(WC_TOOLBAR_MENU, 0);
+
+	/* Extend the dropdown toolbar to the longest string in the list */
+	int width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140);
+	int height = item_count * 10 + 2;
+
+	Point pos = GetToolbarDropdownPos(parent_button, width, height);
+
+	w = AllocateWindow(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
+	w->widget[0].bottom = item_count * 10 + 1;
+	w->flags4 &= ~WF_WHITE_BORDER_MASK;
+
+	WP(w, menu_d).item_count = item_count;
+	WP(w, menu_d).sel_index = 0;
+	WP(w, menu_d).main_button = GB(parent_button, 0, 8);
+	WP(w, menu_d).action_id = (GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button;
+	WP(w, menu_d).string_id = base_string;
+	WP(w, menu_d).checked_items = 0;
+	WP(w, menu_d).disabled_items = disabled_mask;
+
+	_popup_menu_active = true;
+
+	SndPlayFx(SND_15_BEEP);
+	return w;
+}
+
+/* --- Rendering/drawing the player menu --- */
+static int GetPlayerIndexFromMenu(int index)
+{
+	if (index >= 0) {
+		const Player *p;
+
+		FOR_ALL_PLAYERS(p) {
+			if (p->is_active && --index < 0) return p->index;
+		}
+	}
+	return -1;
+}
+
+static void UpdatePlayerMenuHeight(Window *w)
+{
+	byte num = ActivePlayerCount();
+
+	/* Increase one to fit in PlayerList in the menu when in network */
+	if (_networking && WP(w, menu_d).main_button == 9) num++;
+
+	if (WP(w, menu_d).item_count != num) {
+		WP(w, menu_d).item_count = num;
+		SetWindowDirty(w);
+		num = num * 10 + 2;
+		w->height = num;
+		w->widget[0].bottom = w->widget[0].top + num - 1;
+		w->top = GetToolbarDropdownPos(0, w->width, w->height).y;
+		SetWindowDirty(w);
+	}
+}
+
+static void PlayerMenuWndProc(Window *w, WindowEvent *e)
+{
+	switch (e->event) {
+		case WE_PAINT: {
+			UpdatePlayerMenuHeight(w);
+			DrawWindowWidgets(w);
+
+			int x = 1;
+			int y = 1;
+			int sel = WP(w, menu_d).sel_index;
+			int chk = WP(w, menu_d).checked_items; // let this mean gray items.
+
+			/* 9 = playerlist */
+			if (_networking && WP(w, menu_d).main_button == 9) {
+				if (sel == 0) {
+					GfxFillRect(x, y, x + 238, y + 9, 0);
+				}
+				DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING);
+				y += 10;
+				sel--;
+			}
+
+			const Player *p;
+			FOR_ALL_PLAYERS(p) {
+				if (p->is_active) {
+					if (p->index == sel) {
+						GfxFillRect(x, y, x + 238, y + 9, 0);
+					}
+
+					DrawPlayerIcon(p->index, x + 2, y + 1);
+
+					SetDParam(0, p->index);
+					SetDParam(1, p->index);
+
+					TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK;
+					if (chk & 1) color = TC_GREY;
+					DrawString(x + 19, y, STR_7021, color);
+
+					y += 10;
+				}
+				chk >>= 1;
+			}
+		 } break;
+
+		case WE_DESTROY: {
+			Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
+			v->RaiseWidget(WP(w, menu_d).main_button);
+			SetWindowDirty(v);
+			return;
+		}
+
+		case WE_POPUPMENU_SELECT: {
+			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
+			int action_id = WP(w, menu_d).action_id;
+
+			/* We have a new entry at the top of the list of menu 9 when networking
+			*  so keep that in count */
+			if (_networking && WP(w, menu_d).main_button == 9) {
+				if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
+			} else {
+				index = GetPlayerIndexFromMenu(index);
+			}
+
+			if (index < 0) {
+				Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
+				if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
+					index = WP(w, menu_d).sel_index;
+			}
+
+			DeleteWindow(w);
+
+			if (index >= 0) {
+				assert(index >= 0 && index < 30);
+				_menu_clicked_procs[action_id](index);
+			}
+		} break;
+
+		case WE_POPUPMENU_OVER: {
+			int index;
+			UpdatePlayerMenuHeight(w);
+			index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
+
+			/* We have a new entry at the top of the list of menu 9 when networking
+			* so keep that in count */
+			if (_networking && WP(w, menu_d).main_button == 9) {
+				if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
+			} else {
+				index = GetPlayerIndexFromMenu(index);
+			}
+
+			if (index == -1 || index == WP(w, menu_d).sel_index) return;
+
+			WP(w, menu_d).sel_index = index;
+			SetWindowDirty(w);
+			return;
+		}
+	}
+}
+
+static const Widget _player_menu_widgets[] = {
+{    WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
+
+static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray)
+{
+	w->LowerWidget(main_button);
+	w->InvalidateWidget(main_button);
+
+	DeleteWindowById(WC_TOOLBAR_MENU, 0);
+	Point pos = GetToolbarDropdownPos(main_button, 241, 82);
+	w = AllocateWindow(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
+	w->flags4 &= ~WF_WHITE_BORDER_MASK;
+	WP(w, menu_d).item_count = 0;
+	WP(w, menu_d).sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0);
+	if (_networking && main_button == 9) {
+		if (_local_player != PLAYER_SPECTATOR) {
+			WP(w, menu_d).sel_index++;
+		} else {
+			/* Select client list by default for spectators */
+			WP(w, menu_d).sel_index = 0;
+		}
+	}
+	WP(w, menu_d).action_id = main_button;
+	WP(w, menu_d).main_button = main_button;
+	WP(w, menu_d).checked_items = gray;
+	WP(w, menu_d).disabled_items = 0;
+	_popup_menu_active = true;
+	SndPlayFx(SND_15_BEEP);
+	return w;
+}
+
+/* --- Allocating the toolbar --- */
+
 Window *AllocateToolbar()
 {
-	return AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
+	/* Clean old GUI values */
+	_last_built_railtype = RAILTYPE_RAIL;
+	_last_built_roadtype = ROADTYPE_ROAD;
+
+	Window *w = AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
+	if (w == NULL) return NULL;
+
+	CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
+
+	w->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button
+	w->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button
+
+	/* 'w' is for sure a WC_MAIN_TOOLBAR */
+	PositionMainToolbar(w);
+
+	return w;
 }