src/toolbar_gui.cpp
branchNewGRF_ports
changeset 10242 52b4a9006029
parent 10184 fcf5fb2548eb
child 10724 68a692eacf22
equal deleted inserted replaced
10211:c1391c8ed5c6 10242:52b4a9006029
    26 #include "player_gui.h"
    26 #include "player_gui.h"
    27 #include "settings_type.h"
    27 #include "settings_type.h"
    28 #include "toolbar_gui.h"
    28 #include "toolbar_gui.h"
    29 #include "vehicle_base.h"
    29 #include "vehicle_base.h"
    30 #include "gfx_func.h"
    30 #include "gfx_func.h"
       
    31 #include "cheat_func.h"
       
    32 #include "transparency_gui.h"
       
    33 #include "screenshot.h"
       
    34 #include "newgrf_config.h"
       
    35 #include "signs_func.h"
       
    36 #include "fios.h"
       
    37 #include "functions.h"
       
    38 #include "console.h"
       
    39 #include "news_gui.h"
    31 
    40 
    32 #include "network/network.h"
    41 #include "network/network.h"
       
    42 #include "network/network_gui.h"
    33 
    43 
    34 #include "table/strings.h"
    44 #include "table/strings.h"
    35 #include "table/sprites.h"
    45 #include "table/sprites.h"
    36 
    46 
    37 extern void SelectSignTool();
    47 static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask);
    38 extern RailType _last_built_railtype;
    48 static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray);
    39 extern RoadType _last_built_roadtype;
    49 
    40 
    50 RailType _last_built_railtype;
    41 /* Returns the position where the toolbar wants the menu to appear.
    51 RoadType _last_built_roadtype;
       
    52 
       
    53 static void SelectSignTool()
       
    54 {
       
    55 	if (_cursor.sprite == SPR_CURSOR_SIGN) {
       
    56 		ResetObjectToPlace();
       
    57 	} else {
       
    58 		SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, VHM_RECT, WC_MAIN_TOOLBAR, 0);
       
    59 		_place_proc = PlaceProc_Sign;
       
    60 	}
       
    61 }
       
    62 
       
    63 /** Returns the position where the toolbar wants the menu to appear.
    42  * Make sure the dropdown is fully visible within the window.
    64  * Make sure the dropdown is fully visible within the window.
    43  * x + w->left because x is supposed to be the offset of the toolbar-button
    65  * x + w->left because x is supposed to be the offset of the toolbar-button
    44  * we clicked on and w->left the toolbar window itself. So meaning that
    66  * we clicked on and w->left the toolbar window itself. So meaning that
    45  * the default position is aligned with the left side of the clicked button */
    67  * the default position is aligned with the left side of the clicked button */
    46 Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
    68 static Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
    47 {
    69 {
    48 	const Window *w = FindWindowById(WC_MAIN_TOOLBAR,0);
    70 	const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
    49 	Point pos;
    71 	Point pos;
    50 	pos.x = w->widget[GB(parent_button, 0, 8)].left;
    72 	pos.x = w->widget[GB(parent_button, 0, 8)].left;
    51 	pos.x = w->left + Clamp(pos.x, 0, w->width - width);
    73 	pos.x = w->left + Clamp(pos.x, 0, w->width - width);
    52 	pos.y = w->height;
    74 	pos.y = w->height;
    53 
    75 
    54 	return pos;
    76 	return pos;
    55 }
    77 }
    56 
    78 
       
    79 /* --- Pausing --- */
    57 
    80 
    58 static void ToolbarPauseClick(Window *w)
    81 static void ToolbarPauseClick(Window *w)
    59 {
    82 {
    60 	if (_networking && !_network_server) return; // only server can pause the game
    83 	if (_networking && !_network_server) return; // only server can pause the game
    61 
    84 
    62 	if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
    85 	if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
    63 }
    86 }
       
    87 
       
    88 /* --- Fast forwarding --- */
    64 
    89 
    65 static void ToolbarFastForwardClick(Window *w)
    90 static void ToolbarFastForwardClick(Window *w)
    66 {
    91 {
    67 	_fast_forward ^= true;
    92 	_fast_forward ^= true;
    68 	SndPlayFx(SND_15_BEEP);
    93 	SndPlayFx(SND_15_BEEP);
    69 }
    94 }
    70 
    95 
    71 static void ToolbarSaveClick(Window *w)
    96 /* --- Options button menu --- */
    72 {
       
    73 	PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
       
    74 }
       
    75 
       
    76 static void ToolbarMapClick(Window *w)
       
    77 {
       
    78 	PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
       
    79 }
       
    80 
       
    81 static void ToolbarTownClick(Window *w)
       
    82 {
       
    83 	PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
       
    84 }
       
    85 
       
    86 static void ToolbarSubsidiesClick(Window *w)
       
    87 {
       
    88 	PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
       
    89 }
       
    90 
       
    91 static void ToolbarStationsClick(Window *w)
       
    92 {
       
    93 	PopupMainPlayerToolbMenu(w, 7, 0);
       
    94 }
       
    95 
       
    96 static void ToolbarMoneyClick(Window *w)
       
    97 {
       
    98 	PopupMainPlayerToolbMenu(w, 8, 0);
       
    99 }
       
   100 
       
   101 static void ToolbarPlayersClick(Window *w)
       
   102 {
       
   103 	PopupMainPlayerToolbMenu(w, 9, 0);
       
   104 }
       
   105 
       
   106 static void ToolbarGraphsClick(Window *w)
       
   107 {
       
   108 	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
       
   109 }
       
   110 
       
   111 static void ToolbarLeagueClick(Window *w)
       
   112 {
       
   113 	PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
       
   114 }
       
   115 
       
   116 static void ToolbarIndustryClick(Window *w)
       
   117 {
       
   118 	/* Disable build-industry menu if we are a spectator */
       
   119 	PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
       
   120 }
       
   121 
       
   122 static void ToolbarTrainClick(Window *w)
       
   123 {
       
   124 	const Vehicle *v;
       
   125 	int dis = -1;
       
   126 
       
   127 	FOR_ALL_VEHICLES(v) {
       
   128 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner);
       
   129 	}
       
   130 	PopupMainPlayerToolbMenu(w, 13, dis);
       
   131 }
       
   132 
       
   133 static void ToolbarRoadClick(Window *w)
       
   134 {
       
   135 	const Vehicle *v;
       
   136 	int dis = -1;
       
   137 
       
   138 	FOR_ALL_VEHICLES(v) {
       
   139 		if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner);
       
   140 	}
       
   141 	PopupMainPlayerToolbMenu(w, 14, dis);
       
   142 }
       
   143 
       
   144 static void ToolbarShipClick(Window *w)
       
   145 {
       
   146 	const Vehicle *v;
       
   147 	int dis = -1;
       
   148 
       
   149 	FOR_ALL_VEHICLES(v) {
       
   150 		if (v->type == VEH_SHIP) ClrBit(dis, v->owner);
       
   151 	}
       
   152 	PopupMainPlayerToolbMenu(w, 15, dis);
       
   153 }
       
   154 
       
   155 static void ToolbarAirClick(Window *w)
       
   156 {
       
   157 	const Vehicle *v;
       
   158 	int dis = -1;
       
   159 
       
   160 	FOR_ALL_VEHICLES(v) {
       
   161 		if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner);
       
   162 	}
       
   163 	PopupMainPlayerToolbMenu(w, 16, dis);
       
   164 }
       
   165 
       
   166 
       
   167 static void ToolbarZoomInClick(Window *w)
       
   168 {
       
   169 	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   170 		w->HandleButtonClick(17);
       
   171 		SndPlayFx(SND_15_BEEP);
       
   172 	}
       
   173 }
       
   174 
       
   175 static void ToolbarZoomOutClick(Window *w)
       
   176 {
       
   177 	if (DoZoomInOutWindow(ZOOM_OUT,FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   178 		w->HandleButtonClick(18);
       
   179 		SndPlayFx(SND_15_BEEP);
       
   180 	}
       
   181 }
       
   182 
       
   183 static void ToolbarBuildRailClick(Window *w)
       
   184 {
       
   185 	const Player *p = GetPlayer(_local_player);
       
   186 	Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
       
   187 	WP(w2, menu_d).sel_index = _last_built_railtype;
       
   188 }
       
   189 
       
   190 static void ToolbarBuildRoadClick(Window *w)
       
   191 {
       
   192 	const Player *p = GetPlayer(_local_player);
       
   193 	/* The standard road button is *always* available */
       
   194 	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
       
   195 	WP(w2, menu_d).sel_index = _last_built_roadtype;
       
   196 }
       
   197 
       
   198 static void ToolbarBuildWaterClick(Window *w)
       
   199 {
       
   200 	PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
       
   201 }
       
   202 
       
   203 static void ToolbarBuildAirClick(Window *w)
       
   204 {
       
   205 	PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
       
   206 }
       
   207 
       
   208 static void ToolbarForestClick(Window *w)
       
   209 {
       
   210 	PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
       
   211 }
       
   212 
       
   213 static void ToolbarMusicClick(Window *w)
       
   214 {
       
   215 	PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
       
   216 }
       
   217 
       
   218 static void ToolbarNewspaperClick(Window *w)
       
   219 {
       
   220 	PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
       
   221 }
       
   222 
       
   223 static void ToolbarHelpClick(Window *w)
       
   224 {
       
   225 	PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
       
   226 }
       
   227 
    97 
   228 static void ToolbarOptionsClick(Window *w)
    98 static void ToolbarOptionsClick(Window *w)
   229 {
    99 {
   230 	uint16 x = 0;
   100 	uint16 x = 0;
   231 
   101 
   240 	if (IsTransparencySet(TO_HOUSES))                SetBit(x, 12);
   110 	if (IsTransparencySet(TO_HOUSES))                SetBit(x, 12);
   241 	if (IsTransparencySet(TO_SIGNS))                 SetBit(x, 13);
   111 	if (IsTransparencySet(TO_SIGNS))                 SetBit(x, 13);
   242 	WP(w, menu_d).checked_items = x;
   112 	WP(w, menu_d).checked_items = x;
   243 }
   113 }
   244 
   114 
       
   115 static void MenuClickSettings(int index)
       
   116 {
       
   117 	switch (index) {
       
   118 		case 0: ShowGameOptions();      return;
       
   119 		case 1: ShowGameDifficulty();   return;
       
   120 		case 2: ShowPatchesSelection(); return;
       
   121 		case 3: ShowNewGRFSettings(!_networking, true, true, &_grfconfig);   return;
       
   122 		case 4: ShowTransparencyToolbar(); break;
       
   123 
       
   124 		case  6: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES);    break;
       
   125 		case  7: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
       
   126 		case  8: ToggleBit(_display_opt, DO_SHOW_SIGNS);         break;
       
   127 		case  9: ToggleBit(_display_opt, DO_WAYPOINTS);          break;
       
   128 		case 10: ToggleBit(_display_opt, DO_FULL_ANIMATION);     break;
       
   129 		case 11: ToggleBit(_display_opt, DO_FULL_DETAIL);        break;
       
   130 		case 12: ToggleTransparency(TO_HOUSES);                  break;
       
   131 		case 13: ToggleTransparency(TO_SIGNS);                   break;
       
   132 	}
       
   133 	MarkWholeScreenDirty();
       
   134 }
       
   135 
       
   136 /* --- Saving/loading button menu --- */
       
   137 
       
   138 static void ToolbarSaveClick(Window *w)
       
   139 {
       
   140 	PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0);
       
   141 }
   245 
   142 
   246 static void ToolbarScenSaveOrLoad(Window *w)
   143 static void ToolbarScenSaveOrLoad(Window *w)
   247 {
   144 {
   248 	PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
   145 	PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
   249 }
   146 }
       
   147 
       
   148 static void MenuClickSaveLoad(int index)
       
   149 {
       
   150 	if (_game_mode == GM_EDITOR) {
       
   151 		switch (index) {
       
   152 			case 0: ShowSaveLoadDialog(SLD_SAVE_SCENARIO);  break;
       
   153 			case 1: ShowSaveLoadDialog(SLD_LOAD_SCENARIO);  break;
       
   154 			case 2: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
       
   155 			case 3: AskExitToGameMenu();                    break;
       
   156 			case 5: HandleExitGameRequest();                break;
       
   157 		}
       
   158 	} else {
       
   159 		switch (index) {
       
   160 			case 0: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
       
   161 			case 1: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
       
   162 			case 2: AskExitToGameMenu();               break;
       
   163 			case 3: HandleExitGameRequest();           break;
       
   164 		}
       
   165 	}
       
   166 }
       
   167 
       
   168 /* --- Map button menu --- */
       
   169 
       
   170 static void ToolbarMapClick(Window *w)
       
   171 {
       
   172 	PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0);
       
   173 }
       
   174 
       
   175 static void MenuClickMap(int index)
       
   176 {
       
   177 	switch (index) {
       
   178 		case 0: ShowSmallMap();            break;
       
   179 		case 1: ShowExtraViewPortWindow(); break;
       
   180 		case 2: ShowSignList();            break;
       
   181 	}
       
   182 }
       
   183 
       
   184 static void MenuClickScenMap(int index)
       
   185 {
       
   186 	switch (index) {
       
   187 		case 0: ShowSmallMap();            break;
       
   188 		case 1: ShowExtraViewPortWindow(); break;
       
   189 		case 2: ShowSignList();            break;
       
   190 		case 3: ShowTownDirectory();       break;
       
   191 	}
       
   192 }
       
   193 
       
   194 /* --- Town button menu --- */
       
   195 
       
   196 static void ToolbarTownClick(Window *w)
       
   197 {
       
   198 	PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0);
       
   199 }
       
   200 
       
   201 static void MenuClickTown(int index)
       
   202 {
       
   203 	ShowTownDirectory();
       
   204 }
       
   205 
       
   206 /* --- Subidies button menu --- */
       
   207 
       
   208 static void ToolbarSubsidiesClick(Window *w)
       
   209 {
       
   210 	PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0);
       
   211 }
       
   212 
       
   213 static void MenuClickSubsidies(int index)
       
   214 {
       
   215 	ShowSubsidiesList();
       
   216 }
       
   217 
       
   218 /* --- Stations button menu --- */
       
   219 
       
   220 static void ToolbarStationsClick(Window *w)
       
   221 {
       
   222 	PopupMainPlayerToolbMenu(w, 7, 0);
       
   223 }
       
   224 
       
   225 static void MenuClickStations(int index)
       
   226 {
       
   227 	ShowPlayerStations((PlayerID)index);
       
   228 }
       
   229 
       
   230 /* --- Finances button menu --- */
       
   231 
       
   232 static void ToolbarFinancesClick(Window *w)
       
   233 {
       
   234 	PopupMainPlayerToolbMenu(w, 8, 0);
       
   235 }
       
   236 
       
   237 static void MenuClickFinances(int index)
       
   238 {
       
   239 	ShowPlayerFinances((PlayerID)index);
       
   240 }
       
   241 
       
   242 /* --- Company's button menu --- */
       
   243 
       
   244 static void ToolbarPlayersClick(Window *w)
       
   245 {
       
   246 	PopupMainPlayerToolbMenu(w, 9, 0);
       
   247 }
       
   248 
       
   249 static void MenuClickCompany(int index)
       
   250 {
       
   251 	if (_networking && index == 0) {
       
   252 		ShowClientList();
       
   253 	} else {
       
   254 		if (_networking) index--;
       
   255 		ShowPlayerCompany((PlayerID)index);
       
   256 	}
       
   257 }
       
   258 
       
   259 /* --- Graphs button menu --- */
       
   260 
       
   261 static void ToolbarGraphsClick(Window *w)
       
   262 {
       
   263 	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0);
       
   264 }
       
   265 
       
   266 static void MenuClickGraphs(int index)
       
   267 {
       
   268 	switch (index) {
       
   269 		case 0: ShowOperatingProfitGraph();    break;
       
   270 		case 1: ShowIncomeGraph();             break;
       
   271 		case 2: ShowDeliveredCargoGraph();     break;
       
   272 		case 3: ShowPerformanceHistoryGraph(); break;
       
   273 		case 4: ShowCompanyValueGraph();       break;
       
   274 		case 5: ShowCargoPaymentRates();       break;
       
   275 	}
       
   276 }
       
   277 
       
   278 /* --- League button menu --- */
       
   279 
       
   280 static void ToolbarLeagueClick(Window *w)
       
   281 {
       
   282 	PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0);
       
   283 }
       
   284 
       
   285 static void MenuClickLeague(int index)
       
   286 {
       
   287 	switch (index) {
       
   288 		case 0: ShowCompanyLeagueTable();      break;
       
   289 		case 1: ShowPerformanceRatingDetail(); break;
       
   290 	}
       
   291 }
       
   292 
       
   293 /* --- Industries button menu --- */
       
   294 
       
   295 static void ToolbarIndustryClick(Window *w)
       
   296 {
       
   297 	/* Disable build-industry menu if we are a spectator */
       
   298 	PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0);
       
   299 }
       
   300 
       
   301 static void MenuClickIndustry(int index)
       
   302 {
       
   303 	switch (index) {
       
   304 		case 0: ShowIndustryDirectory();   break;
       
   305 		case 1: ShowBuildIndustryWindow(); break;
       
   306 	}
       
   307 }
       
   308 
       
   309 /* --- Trains button menu + 1 helper function for all vehicles. --- */
       
   310 
       
   311 static void ToolbarVehicleClick(Window *w, VehicleType veh)
       
   312 {
       
   313 	const Vehicle *v;
       
   314 	int dis = ~0;
       
   315 
       
   316 	FOR_ALL_VEHICLES(v) {
       
   317 		if (v->type == veh && v->IsPrimaryVehicle()) {
       
   318 			ClrBit(dis, v->owner);
       
   319 			break;
       
   320 		}
       
   321 	}
       
   322 	PopupMainPlayerToolbMenu(w, 13 + veh, dis);
       
   323 }
       
   324 
       
   325 
       
   326 static void ToolbarTrainClick(Window *w)
       
   327 {
       
   328 	ToolbarVehicleClick(w, VEH_TRAIN);
       
   329 }
       
   330 
       
   331 static void MenuClickShowTrains(int index)
       
   332 {
       
   333 	ShowVehicleListWindow((PlayerID)index, VEH_TRAIN);
       
   334 }
       
   335 
       
   336 /* --- Road vehicle button menu --- */
       
   337 
       
   338 static void ToolbarRoadClick(Window *w)
       
   339 {
       
   340 	ToolbarVehicleClick(w, VEH_ROAD);
       
   341 }
       
   342 
       
   343 static void MenuClickShowRoad(int index)
       
   344 {
       
   345 	ShowVehicleListWindow((PlayerID)index, VEH_ROAD);
       
   346 }
       
   347 
       
   348 /* --- Ship button menu --- */
       
   349 
       
   350 static void ToolbarShipClick(Window *w)
       
   351 {
       
   352 	ToolbarVehicleClick(w, VEH_SHIP);
       
   353 }
       
   354 
       
   355 static void MenuClickShowShips(int index)
       
   356 {
       
   357 	ShowVehicleListWindow((PlayerID)index, VEH_SHIP);
       
   358 }
       
   359 
       
   360 /* --- Aircraft button menu --- */
       
   361 
       
   362 static void ToolbarAirClick(Window *w)
       
   363 {
       
   364 	ToolbarVehicleClick(w, VEH_AIRCRAFT);
       
   365 }
       
   366 
       
   367 static void MenuClickShowAir(int index)
       
   368 {
       
   369 	ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT);
       
   370 }
       
   371 
       
   372 /* --- Zoom in button --- */
       
   373 
       
   374 static void ToolbarZoomInClick(Window *w)
       
   375 {
       
   376 	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   377 		w->HandleButtonClick(17);
       
   378 		SndPlayFx(SND_15_BEEP);
       
   379 	}
       
   380 }
       
   381 
       
   382 /* --- Zoom out button --- */
       
   383 
       
   384 static void ToolbarZoomOutClick(Window *w)
       
   385 {
       
   386 	if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
       
   387 		w->HandleButtonClick(18);
       
   388 		SndPlayFx(SND_15_BEEP);
       
   389 	}
       
   390 }
       
   391 
       
   392 /* --- Rail button menu --- */
       
   393 
       
   394 static void ToolbarBuildRailClick(Window *w)
       
   395 {
       
   396 	const Player *p = GetPlayer(_local_player);
       
   397 	Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes);
       
   398 	WP(w2, menu_d).sel_index = _last_built_railtype;
       
   399 }
       
   400 
       
   401 static void MenuClickBuildRail(int index)
       
   402 {
       
   403 	_last_built_railtype = (RailType)index;
       
   404 	ShowBuildRailToolbar(_last_built_railtype, -1);
       
   405 }
       
   406 
       
   407 /* --- Road button menu --- */
       
   408 
       
   409 static void ToolbarBuildRoadClick(Window *w)
       
   410 {
       
   411 	const Player *p = GetPlayer(_local_player);
       
   412 	/* The standard road button is *always* available */
       
   413 	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD));
       
   414 	WP(w2, menu_d).sel_index = _last_built_roadtype;
       
   415 }
       
   416 
       
   417 static void MenuClickBuildRoad(int index)
       
   418 {
       
   419 	_last_built_roadtype = (RoadType)index;
       
   420 	ShowBuildRoadToolbar(_last_built_roadtype);
       
   421 }
       
   422 
       
   423 /* --- Water button menu --- */
       
   424 
       
   425 static void ToolbarBuildWaterClick(Window *w)
       
   426 {
       
   427 	PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0);
       
   428 }
       
   429 
       
   430 static void MenuClickBuildWater(int index)
       
   431 {
       
   432 	ShowBuildDocksToolbar();
       
   433 }
       
   434 
       
   435 /* --- Airport button menu --- */
       
   436 
       
   437 static void ToolbarBuildAirClick(Window *w)
       
   438 {
       
   439 	PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0);
       
   440 }
       
   441 
       
   442 static void MenuClickBuildAir(int index)
       
   443 {
       
   444 	ShowBuildAirToolbar();
       
   445 }
       
   446 
       
   447 /* --- Forest button menu --- */
       
   448 
       
   449 static void ToolbarForestClick(Window *w)
       
   450 {
       
   451 	PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0);
       
   452 }
       
   453 
       
   454 static void MenuClickForest(int index)
       
   455 {
       
   456 	switch (index) {
       
   457 		case 0: ShowTerraformToolbar();  break;
       
   458 		case 1: ShowBuildTreesToolbar(); break;
       
   459 		case 2: SelectSignTool();        break;
       
   460 	}
       
   461 }
       
   462 
       
   463 /* --- Music button menu --- */
       
   464 
       
   465 static void ToolbarMusicClick(Window *w)
       
   466 {
       
   467 	PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0);
       
   468 }
       
   469 
       
   470 static void MenuClickMusicWindow(int index)
       
   471 {
       
   472 	ShowMusicWindow();
       
   473 }
       
   474 
       
   475 /* --- Newspaper button menu --- */
       
   476 
       
   477 static void ToolbarNewspaperClick(Window *w)
       
   478 {
       
   479 	PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0);
       
   480 }
       
   481 
       
   482 static void MenuClickNewspaper(int index)
       
   483 {
       
   484 	switch (index) {
       
   485 		case 0: ShowLastNewsMessage(); break;
       
   486 		case 1: ShowMessageOptions();  break;
       
   487 		case 2: ShowMessageHistory();  break;
       
   488 	}
       
   489 }
       
   490 
       
   491 /* --- Help button menu --- */
       
   492 
       
   493 static void ToolbarHelpClick(Window *w)
       
   494 {
       
   495 	PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0);
       
   496 }
       
   497 
       
   498 static void MenuClickSmallScreenshot()
       
   499 {
       
   500 	SetScreenshotType(SC_VIEWPORT);
       
   501 }
       
   502 
       
   503 static void MenuClickWorldScreenshot()
       
   504 {
       
   505 	SetScreenshotType(SC_WORLD);
       
   506 }
       
   507 
       
   508 static void MenuClickHelp(int index)
       
   509 {
       
   510 	switch (index) {
       
   511 		case 0: PlaceLandBlockInfo();       break;
       
   512 		case 2: IConsoleSwitch();           break;
       
   513 		case 3: MenuClickSmallScreenshot(); break;
       
   514 		case 4: MenuClickWorldScreenshot(); break;
       
   515 		case 5: ShowAboutWindow();          break;
       
   516 	}
       
   517 }
       
   518 
       
   519 /* --- Scenario editor specific handlers. */
   250 
   520 
   251 static void ToolbarScenDateBackward(Window *w)
   521 static void ToolbarScenDateBackward(Window *w)
   252 {
   522 {
   253 	/* don't allow too fast scrolling */
   523 	/* don't allow too fast scrolling */
   254 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
   524 	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
   342 
   612 
   343 static void ToolbarBtn_NULL(Window *w)
   613 static void ToolbarBtn_NULL(Window *w)
   344 {
   614 {
   345 }
   615 }
   346 
   616 
       
   617 
       
   618 /* --- Toolbar handling for the 'normal' case */
   347 
   619 
   348 typedef void ToolbarButtonProc(Window *w);
   620 typedef void ToolbarButtonProc(Window *w);
   349 
   621 
   350 static ToolbarButtonProc * const _toolbar_button_procs[] = {
   622 static ToolbarButtonProc * const _toolbar_button_procs[] = {
   351 	ToolbarPauseClick,
   623 	ToolbarPauseClick,
   354 	ToolbarSaveClick,
   626 	ToolbarSaveClick,
   355 	ToolbarMapClick,
   627 	ToolbarMapClick,
   356 	ToolbarTownClick,
   628 	ToolbarTownClick,
   357 	ToolbarSubsidiesClick,
   629 	ToolbarSubsidiesClick,
   358 	ToolbarStationsClick,
   630 	ToolbarStationsClick,
   359 	ToolbarMoneyClick,
   631 	ToolbarFinancesClick,
   360 	ToolbarPlayersClick,
   632 	ToolbarPlayersClick,
   361 	ToolbarGraphsClick,
   633 	ToolbarGraphsClick,
   362 	ToolbarLeagueClick,
   634 	ToolbarLeagueClick,
   363 	ToolbarIndustryClick,
   635 	ToolbarIndustryClick,
   364 	ToolbarTrainClick,
   636 	ToolbarTrainClick,
   375 	ToolbarMusicClick,
   647 	ToolbarMusicClick,
   376 	ToolbarNewspaperClick,
   648 	ToolbarNewspaperClick,
   377 	ToolbarHelpClick,
   649 	ToolbarHelpClick,
   378 };
   650 };
   379 
   651 
   380 extern void MenuClickSmallScreenshot();
   652 static void MainToolbarWndProc(Window *w, WindowEvent *e)
   381 extern void MenuClickWorldScreenshot();
       
   382 extern void MenuClickSaveLoad(int index);
       
   383 
       
   384 void MainToolbarWndProc(Window *w, WindowEvent *e)
       
   385 {
   653 {
   386 	switch (e->event) {
   654 	switch (e->event) {
   387 		case WE_PAINT:
   655 		case WE_PAINT:
   388 			/* Draw brown-red toolbar bg. */
   656 			/* Draw brown-red toolbar bg. */
   389 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
   657 			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2);
   390 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
   658 			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
   391 
   659 
   392 			/* If spectator, disable all construction buttons
   660 			/* If spectator, disable all construction buttons
   393 			* ie : Build road, rail, ships, airports and landscaping
   661 			* ie : Build road, rail, ships, airports and landscaping
   394 			* Since enabled state is the default, just disable when needed */
   662 			* Since enabled state is the default, just disable when needed */
   395 			w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
   663 			w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END);
   401 
   669 
   402 			DrawWindowWidgets(w);
   670 			DrawWindowWidgets(w);
   403 			break;
   671 			break;
   404 
   672 
   405 		case WE_CLICK:
   673 		case WE_CLICK:
   406 			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget))
   674 			if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) _toolbar_button_procs[e->we.click.widget](w);
   407 				_toolbar_button_procs[e->we.click.widget](w);
       
   408 			break;
   675 			break;
   409 
   676 
   410 		case WE_KEYPRESS:
   677 		case WE_KEYPRESS:
   411 			switch (e->we.keypress.keycode) {
   678 			switch (e->we.keypress.keycode) {
   412 				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
   679 				case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break;
   558 	_toolb_normal_widgets,
   825 	_toolb_normal_widgets,
   559 	MainToolbarWndProc
   826 	MainToolbarWndProc
   560 };
   827 };
   561 
   828 
   562 
   829 
       
   830 /* --- Toolbar handling for the scenario editor */
       
   831 
   563 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
   832 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
   564 	ToolbarPauseClick,
   833 	ToolbarPauseClick,
   565 	ToolbarFastForwardClick,
   834 	ToolbarFastForwardClick,
   566 	ToolbarOptionsClick,
   835 	ToolbarOptionsClick,
   567 	ToolbarScenSaveOrLoad,
   836 	ToolbarScenSaveOrLoad,
   588 	ToolbarMusicClick,
   857 	ToolbarMusicClick,
   589 	NULL,
   858 	NULL,
   590 	ToolbarHelpClick,
   859 	ToolbarHelpClick,
   591 };
   860 };
   592 
   861 
   593 void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
   862 static void ScenEditToolbarWndProc(Window *w, WindowEvent *e)
   594 {
   863 {
   595 	switch (e->event) {
   864 	switch (e->event) {
   596 		case WE_PAINT:
   865 		case WE_PAINT:
   597 			w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR);
   866 			w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR);
   598 			w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR);
   867 			w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR);
   599 
   868 
   600 			/* Draw brown-red toolbar bg. */
   869 			/* Draw brown-red toolbar bg. */
   601 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2);
   870 			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2);
   602 			GfxFillRect(0, 0, w->width-1, w->height-1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
   871 			GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT));
   603 
   872 
   604 			DrawWindowWidgets(w);
   873 			DrawWindowWidgets(w);
   605 
   874 
   606 			SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
   875 			SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
   607 			DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
   876 			DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING);
   664 			SetWindowDirty(w);
   933 			SetWindowDirty(w);
   665 			break;
   934 			break;
   666 
   935 
   667 		case WE_RESIZE: {
   936 		case WE_RESIZE: {
   668 			/* There are 15 buttons plus some spacings if the space allows it.
   937 			/* There are 15 buttons plus some spacings if the space allows it.
   669 			* Furthermore there are two panels of which one is non-essential
   938 			* Furthermore there are two panels of which one is non - essential
   670 			* and that one can be removed is the space is too small. */
   939 			* and that one can be removed is the space is too small. */
   671 			uint buttons_width;
   940 			uint buttons_width;
   672 			uint spacing;
   941 			uint spacing;
   673 
   942 
   674 			static int normal_min_width = (15 * 22) + (2 * 130);
   943 			static int normal_min_width = (15 * 22) + (2 * 130);
   791 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
  1060 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
   792 	_toolb_scen_widgets,
  1061 	_toolb_scen_widgets,
   793 	ScenEditToolbarWndProc
  1062 	ScenEditToolbarWndProc
   794 };
  1063 };
   795 
  1064 
       
  1065 /* --- Rendering/handling the drop down menus --- */
       
  1066 
       
  1067 typedef void MenuClickedProc(int index);
       
  1068 
       
  1069 static MenuClickedProc * const _menu_clicked_procs[] = {
       
  1070 	NULL,                 /* 0 */
       
  1071 	NULL,                 /* 1 */
       
  1072 	MenuClickSettings,    /* 2 */
       
  1073 	MenuClickSaveLoad,    /* 3 */
       
  1074 	MenuClickMap,         /* 4 */
       
  1075 	MenuClickTown,        /* 5 */
       
  1076 	MenuClickSubsidies,   /* 6 */
       
  1077 	MenuClickStations,    /* 7 */
       
  1078 	MenuClickFinances,    /* 8 */
       
  1079 	MenuClickCompany,     /* 9 */
       
  1080 	MenuClickGraphs,      /* 10 */
       
  1081 	MenuClickLeague,      /* 11 */
       
  1082 	MenuClickIndustry,    /* 12 */
       
  1083 	MenuClickShowTrains,  /* 13 */
       
  1084 	MenuClickShowRoad,    /* 14 */
       
  1085 	MenuClickShowShips,   /* 15 */
       
  1086 	MenuClickShowAir,     /* 16 */
       
  1087 	MenuClickScenMap,     /* 17 */
       
  1088 	NULL,                 /* 18 */
       
  1089 	MenuClickBuildRail,   /* 19 */
       
  1090 	MenuClickBuildRoad,   /* 20 */
       
  1091 	MenuClickBuildWater,  /* 21 */
       
  1092 	MenuClickBuildAir,    /* 22 */
       
  1093 	MenuClickForest,      /* 23 */
       
  1094 	MenuClickMusicWindow, /* 24 */
       
  1095 	MenuClickNewspaper,   /* 25 */
       
  1096 	MenuClickHelp,        /* 26 */
       
  1097 };
       
  1098 
       
  1099 static void MenuWndProc(Window *w, WindowEvent *e)
       
  1100 {
       
  1101 	switch (e->event) {
       
  1102 		case WE_CREATE:
       
  1103 			w->widget[0].right = w->width - 1;
       
  1104 			break;
       
  1105 
       
  1106 		case WE_PAINT: {
       
  1107 			byte count = WP(w, menu_d).item_count;
       
  1108 			byte sel = WP(w, menu_d).sel_index;
       
  1109 			uint16 chk = WP(w, menu_d).checked_items;
       
  1110 			StringID string = WP(w, menu_d).string_id;
       
  1111 			byte dis = WP(w, menu_d).disabled_items;
       
  1112 
       
  1113 			DrawWindowWidgets(w);
       
  1114 
       
  1115 			int x = 1;
       
  1116 			int y = 1;
       
  1117 
       
  1118 			for (; count != 0; count--, string++, sel--) {
       
  1119 				TextColour color = HasBit(dis, 0) ? TC_GREY : (sel == 0) ? TC_WHITE : TC_BLACK;
       
  1120 				if (sel == 0) GfxFillRect(x, y, x + w->width - 3, y + 9, 0);
       
  1121 
       
  1122 				if (HasBit(chk, 0)) DrawString(x + 2, y, STR_CHECKMARK, color);
       
  1123 				DrawString(x + 2, y, string, color);
       
  1124 
       
  1125 				y += 10;
       
  1126 				chk >>= 1;
       
  1127 				dis >>= 1;
       
  1128 			}
       
  1129 		} break;
       
  1130 
       
  1131 		case WE_DESTROY: {
       
  1132 				Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
       
  1133 				v->RaiseWidget(WP(w, menu_d).main_button);
       
  1134 				SetWindowDirty(v);
       
  1135 				return;
       
  1136 			}
       
  1137 
       
  1138 		case WE_POPUPMENU_SELECT: {
       
  1139 			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
       
  1140 
       
  1141 			if (index < 0) {
       
  1142 				Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
       
  1143 				if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
       
  1144 					index = WP(w, menu_d).sel_index;
       
  1145 			}
       
  1146 
       
  1147 			int action_id = WP(w, menu_d).action_id;
       
  1148 			DeleteWindow(w);
       
  1149 
       
  1150 			if (index >= 0) {
       
  1151 				assert((uint)index <= lengthof(_menu_clicked_procs));
       
  1152 				_menu_clicked_procs[action_id](index);
       
  1153 			}
       
  1154 
       
  1155 		} break;
       
  1156 
       
  1157 		case WE_POPUPMENU_OVER: {
       
  1158 			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
       
  1159 
       
  1160 			if (index == -1 || index == WP(w, menu_d).sel_index) return;
       
  1161 
       
  1162 			WP(w, menu_d).sel_index = index;
       
  1163 			SetWindowDirty(w);
       
  1164 			return;
       
  1165 		}
       
  1166 	}
       
  1167 }
       
  1168 
       
  1169 /* Dynamic widget length determined by toolbar-string length.
       
  1170  * See PopupMainToolbMenu en MenuWndProc */
       
  1171 static const Widget _menu_widgets[] = {
       
  1172 {    WWT_PANEL, RESIZE_NONE, 14, 0,  0, 0, 0, 0x0, STR_NULL},
       
  1173 { WIDGETS_END},
       
  1174 };
       
  1175 
       
  1176 
       
  1177 /**
       
  1178  * Get the maximum length of a given string in a string-list. This is an
       
  1179  * implicit string-list where the ID's are consecutive
       
  1180  * @param base_string StringID of the first string in the list
       
  1181  * @param count amount of StringID's in the list
       
  1182  * @return the length of the longest string
       
  1183  */
       
  1184 static int GetStringListMaxWidth(StringID base_string, byte count)
       
  1185 {
       
  1186 	char buffer[512];
       
  1187 	int width, max_width = 0;
       
  1188 
       
  1189 	for (byte i = 0; i != count; i++) {
       
  1190 		GetString(buffer, base_string + i, lastof(buffer));
       
  1191 		width = GetStringBoundingBox(buffer).width;
       
  1192 		if (width > max_width) max_width = width;
       
  1193 	}
       
  1194 
       
  1195 	return max_width;
       
  1196 }
       
  1197 
       
  1198 /**
       
  1199  * Show a general dropdown menu. The positioning of the dropdown menu
       
  1200  * defaults to the left side of the parent_button, eg the button that caused
       
  1201  * this window to appear. The only exceptions are when the right side of this
       
  1202  * dropdown would fall outside the main toolbar window, in that case it is
       
  1203  * aligned with the toolbar's right side.
       
  1204  * Since the disable-mask is only 8 bits right now, these dropdowns are
       
  1205  * restricted to 8 items max if any bits of disabled_mask are active.
       
  1206  * @param w Pointer to a window this dropdown menu belongs to. Has no effect
       
  1207  * whatsoever, only graphically for positioning.
       
  1208  * @param parent_button The widget identifier of the button that was clicked for
       
  1209  * this dropdown. The created dropdown then knows what button to raise (button) on
       
  1210  * action and whose function to execute (action).
       
  1211  * It is possible to appoint another button for an action event by setting the
       
  1212  * upper 8 bits of this parameter. If non is set, action is presumed to be the same
       
  1213  * as button. So<br>
       
  1214  * button bits 0 -  7 - widget clicked to get dropdown
       
  1215  * action bits 8 - 15 - function of widget to execute on select (defaults to bits 0 - 7)
       
  1216  * @param base_string The first StringID shown in the dropdown list. All others are
       
  1217  * consecutive indeces from the language file. XXX - fix? Use ingame-string tables?
       
  1218  * @param item_count Number of strings in the list, see previous parameter
       
  1219  * @param disabled_mask Bitmask of disabled strings in the list
       
  1220  * @return Return a pointer to the newly created dropdown window */
       
  1221 static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask)
       
  1222 {
       
  1223 	assert(disabled_mask == 0 || item_count <= 8);
       
  1224 	w->LowerWidget(parent_button);
       
  1225 	w->InvalidateWidget(parent_button);
       
  1226 
       
  1227 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
       
  1228 
       
  1229 	/* Extend the dropdown toolbar to the longest string in the list */
       
  1230 	int width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140);
       
  1231 	int height = item_count * 10 + 2;
       
  1232 
       
  1233 	Point pos = GetToolbarDropdownPos(parent_button, width, height);
       
  1234 
       
  1235 	w = AllocateWindow(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
       
  1236 	w->widget[0].bottom = item_count * 10 + 1;
       
  1237 	w->flags4 &= ~WF_WHITE_BORDER_MASK;
       
  1238 
       
  1239 	WP(w, menu_d).item_count = item_count;
       
  1240 	WP(w, menu_d).sel_index = 0;
       
  1241 	WP(w, menu_d).main_button = GB(parent_button, 0, 8);
       
  1242 	WP(w, menu_d).action_id = (GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button;
       
  1243 	WP(w, menu_d).string_id = base_string;
       
  1244 	WP(w, menu_d).checked_items = 0;
       
  1245 	WP(w, menu_d).disabled_items = disabled_mask;
       
  1246 
       
  1247 	_popup_menu_active = true;
       
  1248 
       
  1249 	SndPlayFx(SND_15_BEEP);
       
  1250 	return w;
       
  1251 }
       
  1252 
       
  1253 /* --- Rendering/drawing the player menu --- */
       
  1254 static int GetPlayerIndexFromMenu(int index)
       
  1255 {
       
  1256 	if (index >= 0) {
       
  1257 		const Player *p;
       
  1258 
       
  1259 		FOR_ALL_PLAYERS(p) {
       
  1260 			if (p->is_active && --index < 0) return p->index;
       
  1261 		}
       
  1262 	}
       
  1263 	return -1;
       
  1264 }
       
  1265 
       
  1266 static void UpdatePlayerMenuHeight(Window *w)
       
  1267 {
       
  1268 	byte num = ActivePlayerCount();
       
  1269 
       
  1270 	/* Increase one to fit in PlayerList in the menu when in network */
       
  1271 	if (_networking && WP(w, menu_d).main_button == 9) num++;
       
  1272 
       
  1273 	if (WP(w, menu_d).item_count != num) {
       
  1274 		WP(w, menu_d).item_count = num;
       
  1275 		SetWindowDirty(w);
       
  1276 		num = num * 10 + 2;
       
  1277 		w->height = num;
       
  1278 		w->widget[0].bottom = w->widget[0].top + num - 1;
       
  1279 		w->top = GetToolbarDropdownPos(0, w->width, w->height).y;
       
  1280 		SetWindowDirty(w);
       
  1281 	}
       
  1282 }
       
  1283 
       
  1284 static void PlayerMenuWndProc(Window *w, WindowEvent *e)
       
  1285 {
       
  1286 	switch (e->event) {
       
  1287 		case WE_PAINT: {
       
  1288 			UpdatePlayerMenuHeight(w);
       
  1289 			DrawWindowWidgets(w);
       
  1290 
       
  1291 			int x = 1;
       
  1292 			int y = 1;
       
  1293 			int sel = WP(w, menu_d).sel_index;
       
  1294 			int chk = WP(w, menu_d).checked_items; // let this mean gray items.
       
  1295 
       
  1296 			/* 9 = playerlist */
       
  1297 			if (_networking && WP(w, menu_d).main_button == 9) {
       
  1298 				if (sel == 0) {
       
  1299 					GfxFillRect(x, y, x + 238, y + 9, 0);
       
  1300 				}
       
  1301 				DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING);
       
  1302 				y += 10;
       
  1303 				sel--;
       
  1304 			}
       
  1305 
       
  1306 			const Player *p;
       
  1307 			FOR_ALL_PLAYERS(p) {
       
  1308 				if (p->is_active) {
       
  1309 					if (p->index == sel) {
       
  1310 						GfxFillRect(x, y, x + 238, y + 9, 0);
       
  1311 					}
       
  1312 
       
  1313 					DrawPlayerIcon(p->index, x + 2, y + 1);
       
  1314 
       
  1315 					SetDParam(0, p->index);
       
  1316 					SetDParam(1, p->index);
       
  1317 
       
  1318 					TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK;
       
  1319 					if (chk & 1) color = TC_GREY;
       
  1320 					DrawString(x + 19, y, STR_7021, color);
       
  1321 
       
  1322 					y += 10;
       
  1323 				}
       
  1324 				chk >>= 1;
       
  1325 			}
       
  1326 		 } break;
       
  1327 
       
  1328 		case WE_DESTROY: {
       
  1329 			Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
       
  1330 			v->RaiseWidget(WP(w, menu_d).main_button);
       
  1331 			SetWindowDirty(v);
       
  1332 			return;
       
  1333 		}
       
  1334 
       
  1335 		case WE_POPUPMENU_SELECT: {
       
  1336 			int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
       
  1337 			int action_id = WP(w, menu_d).action_id;
       
  1338 
       
  1339 			/* We have a new entry at the top of the list of menu 9 when networking
       
  1340 			*  so keep that in count */
       
  1341 			if (_networking && WP(w, menu_d).main_button == 9) {
       
  1342 				if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
       
  1343 			} else {
       
  1344 				index = GetPlayerIndexFromMenu(index);
       
  1345 			}
       
  1346 
       
  1347 			if (index < 0) {
       
  1348 				Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
       
  1349 				if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button)
       
  1350 					index = WP(w, menu_d).sel_index;
       
  1351 			}
       
  1352 
       
  1353 			DeleteWindow(w);
       
  1354 
       
  1355 			if (index >= 0) {
       
  1356 				assert(index >= 0 && index < 30);
       
  1357 				_menu_clicked_procs[action_id](index);
       
  1358 			}
       
  1359 		} break;
       
  1360 
       
  1361 		case WE_POPUPMENU_OVER: {
       
  1362 			int index;
       
  1363 			UpdatePlayerMenuHeight(w);
       
  1364 			index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y);
       
  1365 
       
  1366 			/* We have a new entry at the top of the list of menu 9 when networking
       
  1367 			* so keep that in count */
       
  1368 			if (_networking && WP(w, menu_d).main_button == 9) {
       
  1369 				if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
       
  1370 			} else {
       
  1371 				index = GetPlayerIndexFromMenu(index);
       
  1372 			}
       
  1373 
       
  1374 			if (index == -1 || index == WP(w, menu_d).sel_index) return;
       
  1375 
       
  1376 			WP(w, menu_d).sel_index = index;
       
  1377 			SetWindowDirty(w);
       
  1378 			return;
       
  1379 		}
       
  1380 	}
       
  1381 }
       
  1382 
       
  1383 static const Widget _player_menu_widgets[] = {
       
  1384 {    WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL},
       
  1385 { WIDGETS_END},
       
  1386 };
       
  1387 
       
  1388 static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray)
       
  1389 {
       
  1390 	w->LowerWidget(main_button);
       
  1391 	w->InvalidateWidget(main_button);
       
  1392 
       
  1393 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
       
  1394 	Point pos = GetToolbarDropdownPos(main_button, 241, 82);
       
  1395 	w = AllocateWindow(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
       
  1396 	w->flags4 &= ~WF_WHITE_BORDER_MASK;
       
  1397 	WP(w, menu_d).item_count = 0;
       
  1398 	WP(w, menu_d).sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0);
       
  1399 	if (_networking && main_button == 9) {
       
  1400 		if (_local_player != PLAYER_SPECTATOR) {
       
  1401 			WP(w, menu_d).sel_index++;
       
  1402 		} else {
       
  1403 			/* Select client list by default for spectators */
       
  1404 			WP(w, menu_d).sel_index = 0;
       
  1405 		}
       
  1406 	}
       
  1407 	WP(w, menu_d).action_id = main_button;
       
  1408 	WP(w, menu_d).main_button = main_button;
       
  1409 	WP(w, menu_d).checked_items = gray;
       
  1410 	WP(w, menu_d).disabled_items = 0;
       
  1411 	_popup_menu_active = true;
       
  1412 	SndPlayFx(SND_15_BEEP);
       
  1413 	return w;
       
  1414 }
       
  1415 
       
  1416 /* --- Allocating the toolbar --- */
       
  1417 
   796 Window *AllocateToolbar()
  1418 Window *AllocateToolbar()
   797 {
  1419 {
   798 	return AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
  1420 	/* Clean old GUI values */
   799 }
  1421 	_last_built_railtype = RAILTYPE_RAIL;
       
  1422 	_last_built_roadtype = ROADTYPE_ROAD;
       
  1423 
       
  1424 	Window *w = AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc);
       
  1425 	if (w == NULL) return NULL;
       
  1426 
       
  1427 	CLRBITS(w->flags4, WF_WHITE_BORDER_MASK);
       
  1428 
       
  1429 	w->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button
       
  1430 	w->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button
       
  1431 
       
  1432 	/* 'w' is for sure a WC_MAIN_TOOLBAR */
       
  1433 	PositionMainToolbar(w);
       
  1434 
       
  1435 	return w;
       
  1436 }