src/player_gui.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
child 5650 aefc131bf5ce
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "table/sprites.h"
       
     6 #include "table/strings.h"
       
     7 #include "functions.h"
       
     8 #include "window.h"
       
     9 #include "gui.h"
       
    10 #include "viewport.h"
       
    11 #include "gfx.h"
       
    12 #include "player.h"
       
    13 #include "command.h"
       
    14 #include "vehicle.h"
       
    15 #include "economy.h"
       
    16 #include "network/network.h"
       
    17 #include "variables.h"
       
    18 #include "train.h"
       
    19 #include "date.h"
       
    20 #include "newgrf.h"
       
    21 #include "network/network_data.h"
       
    22 #include "network/network_client.h"
       
    23 
       
    24 static void DoShowPlayerFinances(PlayerID player, bool show_small, bool show_stickied);
       
    25 
       
    26 static void DrawPlayerEconomyStats(const Player *p, byte mode)
       
    27 {
       
    28 	int x,y,i,j,year;
       
    29 	const int64 (*tbl)[13];
       
    30 	int64 sum, cost;
       
    31 	StringID str;
       
    32 
       
    33 	if (!(mode & 1)) { // normal sized economics window (mode&1) is minimized status
       
    34 		/* draw categories */
       
    35 		DrawStringCenterUnderline(61, 15, STR_700F_EXPENDITURE_INCOME, 0);
       
    36 		for (i = 0; i != 13; i++)
       
    37 			DrawString(2, 27 + i*10, STR_7011_CONSTRUCTION + i, 0);
       
    38 		DrawStringRightAligned(111, 27 + 10*13 + 2, STR_7020_TOTAL, 0);
       
    39 
       
    40 		/* draw the price columns */
       
    41 		year = _cur_year - 2;
       
    42 		j = 3;
       
    43 		x = 215;
       
    44 		tbl = p->yearly_expenses + 2;
       
    45 		do {
       
    46 			if (year >= p->inaugurated_year) {
       
    47 				SetDParam(0, year);
       
    48 				DrawStringRightAlignedUnderline(x, 15, STR_7010, 0);
       
    49 				sum = 0;
       
    50 				for (i = 0; i != 13; i++) {
       
    51 					/* draw one row in the price column */
       
    52 					cost = (*tbl)[i];
       
    53 					if (cost != 0) {
       
    54 						sum += cost;
       
    55 
       
    56 						str = STR_701E;
       
    57 						if (cost < 0) { cost = -cost; str++; }
       
    58 						SetDParam64(0, cost);
       
    59 						DrawStringRightAligned(x, 27+i*10, str, 0);
       
    60 					}
       
    61 				}
       
    62 
       
    63 				str = STR_701E;
       
    64 				if (sum < 0) { sum = -sum; str++; }
       
    65 				SetDParam64(0, sum);
       
    66 				DrawStringRightAligned(x, 27 + 13*10 + 2, str, 0);
       
    67 
       
    68 				GfxFillRect(x - 75, 27 + 10*13, x, 27 + 10*13, 215);
       
    69 				x += 95;
       
    70 			}
       
    71 			year++;
       
    72 			tbl--;
       
    73 		} while (--j != 0);
       
    74 
       
    75 		y = 171;
       
    76 
       
    77 		// draw max loan aligned to loan below (y += 10)
       
    78 		SetDParam64(0, (uint64)_economy.max_loan);
       
    79 		DrawString(202, y+10, STR_MAX_LOAN, 0);
       
    80 	} else {
       
    81 		y = 15;
       
    82 	}
       
    83 
       
    84 	DrawString(2, y, STR_7026_BANK_BALANCE, 0);
       
    85 	SetDParam64(0, p->money64);
       
    86 	DrawStringRightAligned(182, y, STR_7028, 0);
       
    87 
       
    88 	y += 10;
       
    89 
       
    90 	DrawString(2, y, STR_7027_LOAN, 0);
       
    91 	SetDParam64(0, p->current_loan);
       
    92 	DrawStringRightAligned(182, y, STR_7028, 0);
       
    93 
       
    94 	y += 12;
       
    95 
       
    96 	GfxFillRect(182 - 75, y-2, 182, y-2, 215);
       
    97 
       
    98 	SetDParam64(0, p->money64 - p->current_loan);
       
    99 	DrawStringRightAligned(182, y, STR_7028, 0);
       
   100 }
       
   101 
       
   102 static const Widget _player_finances_widgets[] = {
       
   103 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
   104 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   379,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   105 {     WWT_IMGBTN,   RESIZE_NONE,    14,   380,   394,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
       
   106 {  WWT_STICKYBOX,   RESIZE_NONE,    14,   395,   406,     0,    13, 0x0,                    STR_STICKY_BUTTON},
       
   107 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   406,    14,   169, 0x0,                    STR_NULL},
       
   108 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   406,   170,   203, 0x0,                    STR_NULL},
       
   109 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,   202,   204,   215, STR_7029_BORROW,        STR_7035_INCREASE_SIZE_OF_LOAN},
       
   110 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   203,   406,   204,   215, STR_702A_REPAY,         STR_7036_REPAY_PART_OF_LOAN},
       
   111 {   WIDGETS_END},
       
   112 };
       
   113 
       
   114 static const Widget _other_player_finances_widgets[] = {
       
   115 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
   116 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   379,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   117 {     WWT_IMGBTN,   RESIZE_NONE,    14,   380,   394,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
       
   118 {  WWT_STICKYBOX,   RESIZE_NONE,    14,   395,   406,     0,    13, 0x0,                    STR_STICKY_BUTTON},
       
   119 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   406,    14,   169, 0x0,                    STR_NULL},
       
   120 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   406,   170,   203, 0x0,                    STR_NULL},
       
   121 {   WIDGETS_END},
       
   122 };
       
   123 
       
   124 static const Widget _other_player_finances_small_widgets[] = {
       
   125 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
   126 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   253,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   127 {     WWT_IMGBTN,   RESIZE_NONE,    14,   254,   267,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
       
   128 {  WWT_STICKYBOX,   RESIZE_NONE,    14,   268,   279,     0,    13, 0x0,                    STR_STICKY_BUTTON},
       
   129 {      WWT_EMPTY,   RESIZE_NONE,     0,     0,     0,     0,     0, 0x0,                    STR_NULL},
       
   130 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   279,    14,    47, 0x0,                    STR_NULL},
       
   131 {   WIDGETS_END},
       
   132 };
       
   133 
       
   134 static const Widget _player_finances_small_widgets[] = {
       
   135 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
   136 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   253,     0,    13, STR_700E_FINANCES,      STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   137 {     WWT_IMGBTN,   RESIZE_NONE,    14,   254,   267,     0,    13, SPR_LARGE_SMALL_WINDOW, STR_7075_TOGGLE_LARGE_SMALL_WINDOW},
       
   138 {  WWT_STICKYBOX,   RESIZE_NONE,    14,   268,   279,     0,    13, 0x0,                    STR_STICKY_BUTTON},
       
   139 {      WWT_EMPTY,   RESIZE_NONE,     0,     0,     0,     0,     0, 0x0,                    STR_NULL},
       
   140 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   279,    14,    47, STR_NULL,               STR_NULL},
       
   141 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,   139,    48,    59, STR_7029_BORROW,        STR_7035_INCREASE_SIZE_OF_LOAN},
       
   142 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   140,   279,    48,    59, STR_702A_REPAY,         STR_7036_REPAY_PART_OF_LOAN},
       
   143 {   WIDGETS_END},
       
   144 };
       
   145 
       
   146 
       
   147 static void PlayerFinancesWndProc(Window *w, WindowEvent *e)
       
   148 {
       
   149 	switch (e->event) {
       
   150 	case WE_PAINT: {
       
   151 		PlayerID player = w->window_number;
       
   152 		const Player *p = GetPlayer(player);
       
   153 
       
   154 		if (player == _local_player) {
       
   155 			/* borrow/repay buttons only exist for local player */
       
   156 			SetWindowWidgetDisabledState(w, 7, p->current_loan == 0);
       
   157 		}
       
   158 
       
   159 		SetDParam(0, p->name_1);
       
   160 		SetDParam(1, p->name_2);
       
   161 		SetDParam(2, GetPlayerNameString(player, 3));
       
   162 		SetDParam(4, 10000);
       
   163 		DrawWindowWidgets(w);
       
   164 
       
   165 		DrawPlayerEconomyStats(p, (byte)WP(w,def_d).data_1);
       
   166 	} break;
       
   167 
       
   168 	case WE_CLICK:
       
   169 		switch (e->we.click.widget) {
       
   170 		case 2: {/* toggle size */
       
   171 			byte mode = (byte)WP(w,def_d).data_1;
       
   172 			bool stickied = !!(w->flags4 & WF_STICKY);
       
   173 			PlayerID player = w->window_number;
       
   174 			DeleteWindow(w);
       
   175 			DoShowPlayerFinances(player, !HASBIT(mode, 0), stickied);
       
   176 		} break;
       
   177 
       
   178 		case 6: /* increase loan */
       
   179 			DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_INCREASE_LOAN | CMD_MSG(STR_702C_CAN_T_BORROW_ANY_MORE_MONEY));
       
   180 			break;
       
   181 
       
   182 		case 7: /* repay loan */
       
   183 			DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_DECREASE_LOAN | CMD_MSG(STR_702F_CAN_T_REPAY_LOAN));
       
   184 			break;
       
   185 		}
       
   186 		break;
       
   187 	}
       
   188 }
       
   189 
       
   190 static const WindowDesc _player_finances_desc = {
       
   191 	WDP_AUTO, WDP_AUTO, 407, 216,
       
   192 	WC_FINANCES,0,
       
   193 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
       
   194 	_player_finances_widgets,
       
   195 	PlayerFinancesWndProc
       
   196 };
       
   197 
       
   198 static const WindowDesc _player_finances_small_desc = {
       
   199 	WDP_AUTO, WDP_AUTO, 280, 60,
       
   200 	WC_FINANCES,0,
       
   201 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
       
   202 	_player_finances_small_widgets,
       
   203 	PlayerFinancesWndProc
       
   204 };
       
   205 
       
   206 static const WindowDesc _other_player_finances_desc = {
       
   207 	WDP_AUTO, WDP_AUTO, 407, 204,
       
   208 	WC_FINANCES,0,
       
   209 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
       
   210 	_other_player_finances_widgets,
       
   211 	PlayerFinancesWndProc
       
   212 };
       
   213 
       
   214 static const WindowDesc _other_player_finances_small_desc = {
       
   215 	WDP_AUTO, WDP_AUTO, 280, 48,
       
   216 	WC_FINANCES,0,
       
   217 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
       
   218 	_other_player_finances_small_widgets,
       
   219 	PlayerFinancesWndProc
       
   220 };
       
   221 
       
   222 static void DoShowPlayerFinances(PlayerID player, bool show_small, bool show_stickied)
       
   223 {
       
   224 	Window *w;
       
   225 	int mode;
       
   226 
       
   227 	static const WindowDesc * const desc_table[2 * 2] = {
       
   228 		&_player_finances_desc, &_player_finances_small_desc,
       
   229 		&_other_player_finances_desc, &_other_player_finances_small_desc,
       
   230 	};
       
   231 
       
   232 	if (!IsValidPlayer(player)) return;
       
   233 
       
   234 	mode = (player != _local_player) * 2 + show_small;
       
   235 	w = AllocateWindowDescFront(desc_table[mode], player);
       
   236 	if (w != NULL) {
       
   237 		w->caption_color = w->window_number;
       
   238 		WP(w,def_d).data_1 = mode;
       
   239 		if (show_stickied) w->flags4 |= WF_STICKY;
       
   240 	}
       
   241 }
       
   242 
       
   243 void ShowPlayerFinances(PlayerID player)
       
   244 {
       
   245 	DoShowPlayerFinances(player, false, false);
       
   246 }
       
   247 
       
   248 /* List of colours for the livery window */
       
   249 static const StringID _colour_dropdown[] = {
       
   250 	STR_00D1_DARK_BLUE,
       
   251 	STR_00D2_PALE_GREEN,
       
   252 	STR_00D3_PINK,
       
   253 	STR_00D4_YELLOW,
       
   254 	STR_00D5_RED,
       
   255 	STR_00D6_LIGHT_BLUE,
       
   256 	STR_00D7_GREEN,
       
   257 	STR_00D8_DARK_GREEN,
       
   258 	STR_00D9_BLUE,
       
   259 	STR_00DA_CREAM,
       
   260 	STR_00DB_MAUVE,
       
   261 	STR_00DC_PURPLE,
       
   262 	STR_00DD_ORANGE,
       
   263 	STR_00DE_BROWN,
       
   264 	STR_00DF_GREY,
       
   265 	STR_00E0_WHITE,
       
   266 	INVALID_STRING_ID
       
   267 };
       
   268 
       
   269 /* Association of liveries to livery classes */
       
   270 static const LiveryClass livery_class[LS_END] = {
       
   271 	LC_OTHER,
       
   272 	LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL,
       
   273 	LC_ROAD, LC_ROAD,
       
   274 	LC_SHIP, LC_SHIP,
       
   275 	LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
       
   276 };
       
   277 
       
   278 /* Number of liveries in each class, used to determine the height of the livery window */
       
   279 static const byte livery_height[] = {
       
   280 	1,
       
   281 	11,
       
   282 	2,
       
   283 	2,
       
   284 	3,
       
   285 };
       
   286 
       
   287 typedef struct livery_d {
       
   288 	uint32 sel;
       
   289 	LiveryClass livery_class;
       
   290 } livery_d;
       
   291 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(livery_d));
       
   292 
       
   293 static void ShowColourDropDownMenu(Window *w, uint32 widget)
       
   294 {
       
   295 	uint32 used_colours = 0;
       
   296 	const Livery *livery;
       
   297 	LiveryScheme scheme;
       
   298 
       
   299 	/* Disallow other player colours for the primary colour */
       
   300 	if (HASBIT(WP(w, livery_d).sel, LS_DEFAULT) && widget == 10) {
       
   301 		const Player *p;
       
   302 		FOR_ALL_PLAYERS(p) {
       
   303 			if (p->is_active && p->index != _local_player) SETBIT(used_colours, p->player_color);
       
   304 		}
       
   305 	}
       
   306 
       
   307 	/* Get the first selected livery to use as the default dropdown item */
       
   308 	for (scheme = 0; scheme < LS_END; scheme++) {
       
   309 		if (HASBIT(WP(w, livery_d).sel, scheme)) break;
       
   310 	}
       
   311 	if (scheme == LS_END) scheme = LS_DEFAULT;
       
   312 	livery = &GetPlayer(w->window_number)->livery[scheme];
       
   313 
       
   314 	ShowDropDownMenu(w, _colour_dropdown, widget == 10 ? livery->colour1 : livery->colour2, widget, used_colours, 0);
       
   315 }
       
   316 
       
   317 static void SelectPlayerLiveryWndProc(Window *w, WindowEvent *e)
       
   318 {
       
   319 	switch (e->event) {
       
   320 		case WE_CREATE:
       
   321 			LowerWindowWidget(w, WP(w, livery_d).livery_class + 2);
       
   322 			if (!_have_2cc) {
       
   323 				HideWindowWidget(w, 11);
       
   324 				HideWindowWidget(w, 12);
       
   325 			}
       
   326 			break;
       
   327 
       
   328 		case WE_PAINT: {
       
   329 			const Player *p = GetPlayer(w->window_number);
       
   330 			LiveryScheme scheme = LS_DEFAULT;
       
   331 			int y = 51;
       
   332 
       
   333 			/* Disable dropdown controls if no scheme is selected */
       
   334 			SetWindowWidgetDisabledState(w,  9, (WP(w, livery_d).sel == 0));
       
   335 			SetWindowWidgetDisabledState(w, 10, (WP(w, livery_d).sel == 0));
       
   336 			SetWindowWidgetDisabledState(w, 11, (WP(w, livery_d).sel == 0));
       
   337 			SetWindowWidgetDisabledState(w, 12, (WP(w, livery_d).sel == 0));
       
   338 
       
   339 			if (!(WP(w, livery_d).sel == 0)) {
       
   340 				for (scheme = 0; scheme < LS_END; scheme++) {
       
   341 					if (HASBIT(WP(w, livery_d).sel, scheme)) break;
       
   342 				}
       
   343 				if (scheme == LS_END) scheme = LS_DEFAULT;
       
   344 			}
       
   345 
       
   346 			SetDParam(0, STR_00D1_DARK_BLUE + p->livery[scheme].colour1);
       
   347 			SetDParam(1, STR_00D1_DARK_BLUE + p->livery[scheme].colour2);
       
   348 
       
   349 			DrawWindowWidgets(w);
       
   350 
       
   351 			for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
       
   352 				if (livery_class[scheme] == WP(w, livery_d).livery_class) {
       
   353 					bool sel = HASBIT(WP(w, livery_d).sel, scheme) != 0;
       
   354 
       
   355 					if (scheme != LS_DEFAULT) {
       
   356 						DrawSprite(p->livery[scheme].in_use ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, 2, y);
       
   357 					}
       
   358 
       
   359 					DrawString(15, y, STR_LIVERY_DEFAULT + scheme, sel ? 0xC : 0x10);
       
   360 
       
   361 					DrawSprite(SPR_SQUARE | GENERAL_SPRITE_COLOR(p->livery[scheme].colour1) | PALETTE_MODIFIER_COLOR, 152, y);
       
   362 					DrawString(165, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour1, sel ? 0xC : 2);
       
   363 
       
   364 					if (_have_2cc) {
       
   365 						DrawSprite(SPR_SQUARE | GENERAL_SPRITE_COLOR(p->livery[scheme].colour2) | PALETTE_MODIFIER_COLOR, 277, y);
       
   366 						DrawString(290, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour2, sel ? 0xC : 2);
       
   367 					}
       
   368 
       
   369 					y += 14;
       
   370 				}
       
   371 			}
       
   372 			break;
       
   373 		}
       
   374 
       
   375 		case WE_CLICK: {
       
   376 			switch (e->we.click.widget) {
       
   377 				/* Livery Class buttons */
       
   378 				case 2:
       
   379 				case 3:
       
   380 				case 4:
       
   381 				case 5:
       
   382 				case 6: {
       
   383 					LiveryScheme scheme;
       
   384 
       
   385 					RaiseWindowWidget(w, WP(w, livery_d).livery_class + 2);
       
   386 					WP(w, livery_d).livery_class = e->we.click.widget - 2;
       
   387 					WP(w, livery_d).sel = 0;
       
   388 					LowerWindowWidget(w, WP(w, livery_d).livery_class + 2);
       
   389 
       
   390 					/* Select the first item in the list */
       
   391 					for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
       
   392 						if (livery_class[scheme] == WP(w, livery_d).livery_class) {
       
   393 							WP(w, livery_d).sel = 1 << scheme;
       
   394 							break;
       
   395 						}
       
   396 					}
       
   397 					w->height = 49 + livery_height[WP(w, livery_d).livery_class] * 14;
       
   398 					w->widget[13].bottom = w->height - 1;
       
   399 					w->widget[13].data = livery_height[WP(w, livery_d).livery_class] << 8 | 1;
       
   400 					MarkWholeScreenDirty();
       
   401 					break;
       
   402 				}
       
   403 
       
   404 				case 9:
       
   405 				case 10: // First colour dropdown
       
   406 					ShowColourDropDownMenu(w, 10);
       
   407 					break;
       
   408 
       
   409 				case 11:
       
   410 				case 12: // Second colour dropdown
       
   411 					ShowColourDropDownMenu(w, 12);
       
   412 					break;
       
   413 
       
   414 				case 13: {
       
   415 					LiveryScheme scheme;
       
   416 					LiveryScheme j = (e->we.click.pt.y - 48) / 14;
       
   417 
       
   418 					for (scheme = 0; scheme <= j; scheme++) {
       
   419 						if (livery_class[scheme] != WP(w, livery_d).livery_class) j++;
       
   420 						if (scheme >= LS_END) return;
       
   421 					}
       
   422 					if (j >= LS_END) return;
       
   423 
       
   424 					/* If clicking on the left edge, toggle using the livery */
       
   425 					if (e->we.click.pt.x < 10) {
       
   426 						DoCommandP(0, j | (2 << 8), !GetPlayer(w->window_number)->livery[j].in_use, NULL, CMD_SET_PLAYER_COLOR);
       
   427 					}
       
   428 
       
   429 					if (_ctrl_pressed) {
       
   430 						TOGGLEBIT(WP(w, livery_d).sel, j);
       
   431 					} else {
       
   432 						WP(w, livery_d).sel = 1 << j;
       
   433 					}
       
   434 					SetWindowDirty(w);
       
   435 					break;
       
   436 				}
       
   437 			}
       
   438 			break;
       
   439 		}
       
   440 
       
   441 		case WE_DROPDOWN_SELECT: {
       
   442 			LiveryScheme scheme;
       
   443 
       
   444 			for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
       
   445 				if (HASBIT(WP(w, livery_d).sel, scheme)) {
       
   446 					DoCommandP(0, scheme | (e->we.dropdown.button == 10 ? 0 : 256), e->we.dropdown.index, NULL, CMD_SET_PLAYER_COLOR);
       
   447 				}
       
   448 			}
       
   449 			break;
       
   450 		}
       
   451 	}
       
   452 }
       
   453 
       
   454 static const Widget _select_player_livery_2cc_widgets[] = {
       
   455 { WWT_CLOSEBOX, RESIZE_NONE, 14,   0,  10,   0,  13, STR_00C5,                  STR_018B_CLOSE_WINDOW },
       
   456 {  WWT_CAPTION, RESIZE_NONE, 14,  11, 399,   0,  13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS },
       
   457 {   WWT_IMGBTN, RESIZE_NONE, 14,   0,  21,  14,  35, SPR_IMG_COMPANY_GENERAL,   STR_LIVERY_GENERAL_TIP },
       
   458 {   WWT_IMGBTN, RESIZE_NONE, 14,  22,  43,  14,  35, SPR_IMG_TRAINLIST,         STR_LIVERY_TRAIN_TIP },
       
   459 {   WWT_IMGBTN, RESIZE_NONE, 14,  44,  65,  14,  35, SPR_IMG_TRUCKLIST,         STR_LIVERY_ROADVEH_TIP },
       
   460 {   WWT_IMGBTN, RESIZE_NONE, 14,  66,  87,  14,  35, SPR_IMG_SHIPLIST,          STR_LIVERY_SHIP_TIP },
       
   461 {   WWT_IMGBTN, RESIZE_NONE, 14,  88, 109,  14,  35, SPR_IMG_AIRPLANESLIST,     STR_LIVERY_AIRCRAFT_TIP },
       
   462 {    WWT_PANEL, RESIZE_NONE, 14, 110, 399,  14,  35, 0x0,                       STR_NULL },
       
   463 {    WWT_PANEL, RESIZE_NONE, 14,   0, 149,  36,  47, 0x0,                       STR_NULL },
       
   464 {  WWT_TEXTBTN, RESIZE_NONE, 14, 150, 262,  36,  47, STR_02BD,                  STR_LIVERY_PRIMARY_TIP },
       
   465 {  WWT_TEXTBTN, RESIZE_NONE, 14, 263, 274,  36,  47, STR_0225,                  STR_LIVERY_PRIMARY_TIP },
       
   466 {  WWT_TEXTBTN, RESIZE_NONE, 14, 275, 387,  36,  47, STR_02E1,                  STR_LIVERY_SECONDARY_TIP },
       
   467 {  WWT_TEXTBTN, RESIZE_NONE, 14, 388, 399,  36,  47, STR_0225,                  STR_LIVERY_SECONDARY_TIP },
       
   468 {   WWT_MATRIX, RESIZE_NONE, 14,   0, 399,  48,  48 + 1 * 14, (1 << 8) | 1,     STR_LIVERY_PANEL_TIP },
       
   469 { WIDGETS_END },
       
   470 };
       
   471 
       
   472 static const WindowDesc _select_player_livery_2cc_desc = {
       
   473 	WDP_AUTO, WDP_AUTO, 400, 49 + 1 * 14,
       
   474 	WC_PLAYER_COLOR, 0,
       
   475 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   476 	_select_player_livery_2cc_widgets,
       
   477 	SelectPlayerLiveryWndProc
       
   478 };
       
   479 
       
   480 
       
   481 static const Widget _select_player_livery_widgets[] = {
       
   482 { WWT_CLOSEBOX, RESIZE_NONE, 14,   0,  10,   0,  13, STR_00C5,                  STR_018B_CLOSE_WINDOW },
       
   483 {  WWT_CAPTION, RESIZE_NONE, 14,  11, 274,   0,  13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS },
       
   484 {   WWT_IMGBTN, RESIZE_NONE, 14,   0,  21,  14,  35, SPR_IMG_COMPANY_GENERAL,   STR_LIVERY_GENERAL_TIP },
       
   485 {   WWT_IMGBTN, RESIZE_NONE, 14,  22,  43,  14,  35, SPR_IMG_TRAINLIST,         STR_LIVERY_TRAIN_TIP },
       
   486 {   WWT_IMGBTN, RESIZE_NONE, 14,  44,  65,  14,  35, SPR_IMG_TRUCKLIST,         STR_LIVERY_ROADVEH_TIP },
       
   487 {   WWT_IMGBTN, RESIZE_NONE, 14,  66,  87,  14,  35, SPR_IMG_SHIPLIST,          STR_LIVERY_SHIP_TIP },
       
   488 {   WWT_IMGBTN, RESIZE_NONE, 14,  88, 109,  14,  35, SPR_IMG_AIRPLANESLIST,     STR_LIVERY_AIRCRAFT_TIP },
       
   489 {    WWT_PANEL, RESIZE_NONE, 14, 110, 274,  14,  35, 0x0,                       STR_NULL },
       
   490 {    WWT_PANEL, RESIZE_NONE, 14,   0, 149,  36,  47, 0x0,                       STR_NULL },
       
   491 {  WWT_TEXTBTN, RESIZE_NONE, 14, 150, 262,  36,  47, STR_02BD,                  STR_LIVERY_PRIMARY_TIP },
       
   492 {  WWT_TEXTBTN, RESIZE_NONE, 14, 263, 274,  36,  47, STR_0225,                  STR_LIVERY_PRIMARY_TIP },
       
   493 {  WWT_TEXTBTN, RESIZE_NONE, 14, 275, 275,  36,  47, STR_02E1,                  STR_LIVERY_SECONDARY_TIP },
       
   494 {  WWT_TEXTBTN, RESIZE_NONE, 14, 275, 275,  36,  47, STR_0225,                  STR_LIVERY_SECONDARY_TIP },
       
   495 {   WWT_MATRIX, RESIZE_NONE, 14,   0, 274,  48,  48 + 1 * 14, (1 << 8) | 1,     STR_LIVERY_PANEL_TIP },
       
   496 { WIDGETS_END },
       
   497 };
       
   498 
       
   499 static const WindowDesc _select_player_livery_desc = {
       
   500 	WDP_AUTO, WDP_AUTO, 275, 49 + 1 * 14,
       
   501 	WC_PLAYER_COLOR, 0,
       
   502 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   503 	_select_player_livery_widgets,
       
   504 	SelectPlayerLiveryWndProc
       
   505 };
       
   506 
       
   507 static void SelectPlayerFaceWndProc(Window *w, WindowEvent *e)
       
   508 {
       
   509 	switch (e->event) {
       
   510 	case WE_PAINT: {
       
   511 		Player *p;
       
   512 		LowerWindowWidget(w, WP(w, facesel_d).gender + 5);
       
   513 		DrawWindowWidgets(w);
       
   514 		p = GetPlayer(w->window_number);
       
   515 		DrawPlayerFace(WP(w,facesel_d).face, p->player_color, 2, 16);
       
   516 	} break;
       
   517 
       
   518 	case WE_CLICK:
       
   519 		switch (e->we.click.widget) {
       
   520 		case 3: DeleteWindow(w); break;
       
   521 		case 4: /* ok click */
       
   522 			DoCommandP(0, 0, WP(w,facesel_d).face, NULL, CMD_SET_PLAYER_FACE);
       
   523 			DeleteWindow(w);
       
   524 			break;
       
   525 		case 5: /* male click */
       
   526 		case 6: /* female click */
       
   527 			RaiseWindowWidget(w, WP(w, facesel_d).gender + 5);
       
   528 			WP(w, facesel_d).gender = e->we.click.widget - 5;
       
   529 			LowerWindowWidget(w, WP(w, facesel_d).gender + 5);
       
   530 			SetWindowDirty(w);
       
   531 			break;
       
   532 		case 7:
       
   533 			WP(w,facesel_d).face = (WP(w,facesel_d).gender << 31) + GB(InteractiveRandom(), 0, 31);
       
   534 			SetWindowDirty(w);
       
   535 			break;
       
   536 		}
       
   537 		break;
       
   538 	}
       
   539 }
       
   540 
       
   541 static const Widget _select_player_face_widgets[] = {
       
   542 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                STR_018B_CLOSE_WINDOW},
       
   543 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   189,     0,    13, STR_7043_FACE_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   544 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   189,    14,   136, 0x0,                     STR_NULL},
       
   545 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,    94,   137,   148, STR_012E_CANCEL,         STR_7047_CANCEL_NEW_FACE_SELECTION},
       
   546 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,    95,   189,   137,   148, STR_012F_OK,             STR_7048_ACCEPT_NEW_FACE_SELECTION},
       
   547 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    95,   187,    25,    36, STR_7044_MALE,           STR_7049_SELECT_MALE_FACES},
       
   548 {    WWT_TEXTBTN,   RESIZE_NONE,    14,    95,   187,    37,    48, STR_7045_FEMALE,         STR_704A_SELECT_FEMALE_FACES},
       
   549 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,    95,   187,    79,    90, STR_7046_NEW_FACE,       STR_704B_GENERATE_RANDOM_NEW_FACE},
       
   550 {   WIDGETS_END},
       
   551 };
       
   552 
       
   553 static const WindowDesc _select_player_face_desc = {
       
   554 	WDP_AUTO, WDP_AUTO, 190, 149,
       
   555 	WC_PLAYER_FACE,0,
       
   556 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
       
   557 	_select_player_face_widgets,
       
   558 	SelectPlayerFaceWndProc
       
   559 };
       
   560 
       
   561 /* Names of the widgets. Keep them in the same order as in the widget array */
       
   562 enum PlayerCompanyWindowWidgets {
       
   563 	PCW_WIDGET_CLOSEBOX = 0,
       
   564 	PCW_WIDGET_CAPTION,
       
   565 	PCW_WIDGET_FACE,
       
   566 	PCW_WIDGET_NEW_FACE,
       
   567 	PCW_WIDGET_COLOR_SCHEME,
       
   568 	PCW_WIDGET_PRESIDENT_NAME,
       
   569 	PCW_WIDGET_COMPANY_NAME,
       
   570 	PCW_WIDGET_BUILD_VIEW_HQ,
       
   571 	PCW_WIDGET_RELOCATE_HQ,
       
   572 	PCW_WIDGET_BUY_SHARE,
       
   573 	PCW_WIDGET_SELL_SHARE,
       
   574 	PCW_WIDGET_COMPANY_PASSWORD,
       
   575 };
       
   576 
       
   577 static const Widget _player_company_widgets[] = {
       
   578 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
       
   579 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   359,     0,    13, STR_7001,                          STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   580 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   359,    14,   157, 0x0,                               STR_NULL},
       
   581 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,    89,   158,   169, STR_7004_NEW_FACE,                 STR_7030_SELECT_NEW_FACE_FOR_PRESIDENT},
       
   582 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,    90,   179,   158,   169, STR_7005_COLOR_SCHEME,             STR_7031_CHANGE_THE_COMPANY_VEHICLE},
       
   583 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   180,   269,   158,   169, STR_7009_PRESIDENT_NAME,           STR_7032_CHANGE_THE_PRESIDENT_S},
       
   584 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   270,   359,   158,   169, STR_7008_COMPANY_NAME,             STR_7033_CHANGE_THE_COMPANY_NAME},
       
   585 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   266,   355,    18,    29, STR_7072_VIEW_HQ,                  STR_7070_BUILD_COMPANY_HEADQUARTERS},
       
   586 {    WWT_TEXTBTN,   RESIZE_NONE,    14,   266,   355,    32,    43, STR_RELOCATE_HQ,                   STR_RELOCATE_COMPANY_HEADQUARTERS},
       
   587 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,   179,   158,   169, STR_7077_BUY_25_SHARE_IN_COMPANY,  STR_7079_BUY_25_SHARE_IN_THIS_COMPANY},
       
   588 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   180,   359,   158,   169, STR_7078_SELL_25_SHARE_IN_COMPANY, STR_707A_SELL_25_SHARE_IN_THIS_COMPANY},
       
   589 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   266,   355,   138,   149, STR_COMPANY_PASSWORD,              STR_COMPANY_PASSWORD_TOOLTIP},
       
   590 {   WIDGETS_END},
       
   591 };
       
   592 
       
   593 static void DrawPlayerVehiclesAmount(PlayerID player)
       
   594 {
       
   595 	const int x = 110;
       
   596 	int y = 72;
       
   597 	const Vehicle *v;
       
   598 	uint train = 0;
       
   599 	uint road  = 0;
       
   600 	uint air   = 0;
       
   601 	uint ship  = 0;
       
   602 
       
   603 	DrawString(x, y, STR_7039_VEHICLES, 0);
       
   604 
       
   605 	FOR_ALL_VEHICLES(v) {
       
   606 		if (v->owner == player) {
       
   607 			switch (v->type) {
       
   608 				case VEH_Train:    if (IsFrontEngine(v)) train++; break;
       
   609 				case VEH_Road:     road++; break;
       
   610 				case VEH_Aircraft: if (v->subtype <= 2) air++; break;
       
   611 				case VEH_Ship:     ship++; break;
       
   612 				default: break;
       
   613 			}
       
   614 		}
       
   615 	}
       
   616 
       
   617 	if (train+road+air+ship == 0) {
       
   618 		DrawString(x+70, y, STR_7042_NONE, 0);
       
   619 	} else {
       
   620 		if (train != 0) {
       
   621 			SetDParam(0, train);
       
   622 			DrawString(x + 70, y, STR_TRAINS, 0);
       
   623 			y += 10;
       
   624 		}
       
   625 
       
   626 		if (road != 0) {
       
   627 			SetDParam(0, road);
       
   628 			DrawString(x + 70, y, STR_ROAD_VEHICLES, 0);
       
   629 			y += 10;
       
   630 		}
       
   631 
       
   632 		if (air != 0) {
       
   633 			SetDParam(0, air);
       
   634 			DrawString(x + 70, y, STR_AIRCRAFT, 0);
       
   635 			y += 10;
       
   636 		}
       
   637 
       
   638 		if (ship != 0) {
       
   639 			SetDParam(0, ship);
       
   640 			DrawString(x + 70, y, STR_SHIPS, 0);
       
   641 		}
       
   642 	}
       
   643 }
       
   644 
       
   645 int GetAmountOwnedBy(const Player *p, PlayerID owner)
       
   646 {
       
   647 	return (p->share_owners[0] == owner) +
       
   648 				 (p->share_owners[1] == owner) +
       
   649 				 (p->share_owners[2] == owner) +
       
   650 				 (p->share_owners[3] == owner);
       
   651 }
       
   652 
       
   653 static void DrawCompanyOwnerText(const Player *p)
       
   654 {
       
   655 	const Player *p2;
       
   656 	int num = -1;
       
   657 
       
   658 	FOR_ALL_PLAYERS(p2) {
       
   659 		uint amt = GetAmountOwnedBy(p, p2->index);
       
   660 		if (amt != 0) {
       
   661 			num++;
       
   662 
       
   663 			SetDParam(num * 3 + 0, amt * 25);
       
   664 			SetDParam(num * 3 + 1, p2->name_1);
       
   665 			SetDParam(num * 3 + 2, p2->name_2);
       
   666 
       
   667 			if (num != 0) break;
       
   668 		}
       
   669 	}
       
   670 
       
   671 	if (num >= 0) DrawString(120, 124, STR_707D_OWNED_BY + num, 0);
       
   672 }
       
   673 
       
   674 static void PlayerCompanyWndProc(Window *w, WindowEvent *e)
       
   675 {
       
   676 	switch (e->event) {
       
   677 		case WE_PAINT: {
       
   678 			const Player *p = GetPlayer(w->window_number);
       
   679 			bool local = w->window_number == _local_player;
       
   680 
       
   681 			SetWindowWidgetHiddenState(w, PCW_WIDGET_NEW_FACE,       !local);
       
   682 			SetWindowWidgetHiddenState(w, PCW_WIDGET_COLOR_SCHEME,   !local);
       
   683 			SetWindowWidgetHiddenState(w, PCW_WIDGET_PRESIDENT_NAME, !local);
       
   684 			SetWindowWidgetHiddenState(w, PCW_WIDGET_COMPANY_NAME,   !local);
       
   685 			w->widget[PCW_WIDGET_BUILD_VIEW_HQ].data = (local && p->location_of_house == 0) ? STR_706F_BUILD_HQ : STR_7072_VIEW_HQ;
       
   686 			if (local && p->location_of_house != 0) w->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; //HQ is already built.
       
   687 			SetWindowWidgetDisabledState(w, PCW_WIDGET_BUILD_VIEW_HQ, !local && p->location_of_house == 0);
       
   688 			SetWindowWidgetHiddenState(w, PCW_WIDGET_RELOCATE_HQ,      !local || p->location_of_house == 0);
       
   689 			SetWindowWidgetHiddenState(w, PCW_WIDGET_BUY_SHARE,        local);
       
   690 			SetWindowWidgetHiddenState(w, PCW_WIDGET_SELL_SHARE,       local);
       
   691 			SetWindowWidgetHiddenState(w, PCW_WIDGET_COMPANY_PASSWORD, !local || !_networking);
       
   692 
       
   693 			if (!local) {
       
   694 				if (_patches.allow_shares) { // Shares are allowed
       
   695 					/* If all shares are owned by someone (none by nobody), disable buy button */
       
   696 					SetWindowWidgetDisabledState(w, PCW_WIDGET_BUY_SHARE, GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0 ||
       
   697 							/* Only 25% left to buy. If the player is human, disable buying it up.. TODO issues! */
       
   698 							(GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 1 && !p->is_ai) ||
       
   699 							/* Spectators cannot do anything of course */
       
   700 							_local_player == PLAYER_SPECTATOR);
       
   701 
       
   702 					/* If the player doesn't own any shares, disable sell button */
       
   703 					SetWindowWidgetDisabledState(w, PCW_WIDGET_SELL_SHARE, (GetAmountOwnedBy(p, _local_player) == 0) ||
       
   704 							/* Spectators cannot do anything of course */
       
   705 							_local_player == PLAYER_SPECTATOR);
       
   706 				} else { // Shares are not allowed, disable buy/sell buttons
       
   707 					DisableWindowWidget(w, PCW_WIDGET_BUY_SHARE);
       
   708 					DisableWindowWidget(w, PCW_WIDGET_SELL_SHARE);
       
   709 				}
       
   710 			}
       
   711 
       
   712 			SetDParam(0, p->name_1);
       
   713 			SetDParam(1, p->name_2);
       
   714 			SetDParam(2, GetPlayerNameString((byte)w->window_number, 3));
       
   715 
       
   716 			DrawWindowWidgets(w);
       
   717 
       
   718 			SetDParam(0, p->inaugurated_year);
       
   719 			DrawString(110, 25, STR_7038_INAUGURATED, 0);
       
   720 
       
   721 			DrawPlayerVehiclesAmount(w->window_number);
       
   722 
       
   723 			DrawString(110,48, STR_7006_COLOR_SCHEME, 0);
       
   724 			// Draw company-colour bus
       
   725 			DrawSprite(PLAYER_SPRITE_COLOR(p->index) + SPRITE_PALETTE(SPR_VEH_BUS_SW_VIEW), 215, 49);
       
   726 
       
   727 			DrawPlayerFace(p->face, p->player_color, 2, 16);
       
   728 
       
   729 			SetDParam(0, p->president_name_1);
       
   730 			SetDParam(1, p->president_name_2);
       
   731 			DrawStringMultiCenter(48, 141, STR_7037_PRESIDENT, 94);
       
   732 
       
   733 			SetDParam64(0, CalculateCompanyValue(p));
       
   734 			DrawString(110, 114, STR_7076_COMPANY_VALUE, 0);
       
   735 
       
   736 			DrawCompanyOwnerText(p);
       
   737 
       
   738 			break;
       
   739 		}
       
   740 
       
   741 		case WE_CLICK:
       
   742 			switch (e->we.click.widget) {
       
   743 				case PCW_WIDGET_NEW_FACE: {
       
   744 					Window *wf = AllocateWindowDescFront(&_select_player_face_desc, w->window_number);
       
   745 					if (wf != NULL) {
       
   746 						wf->caption_color = w->window_number;
       
   747 						WP(wf,facesel_d).face = GetPlayer(wf->window_number)->face;
       
   748 						WP(wf,facesel_d).gender = 0;
       
   749 					}
       
   750 					break;
       
   751 				}
       
   752 
       
   753 				case PCW_WIDGET_COLOR_SCHEME: {
       
   754 					Window *wf = AllocateWindowDescFront(_have_2cc ? &_select_player_livery_2cc_desc : &_select_player_livery_desc, w->window_number);
       
   755 					if (wf != NULL) {
       
   756 						wf->caption_color = wf->window_number;
       
   757 						WP(wf,livery_d).livery_class = LC_OTHER;
       
   758 						WP(wf,livery_d).sel = 1;
       
   759 						LowerWindowWidget(wf, 2);
       
   760 					}
       
   761 					break;
       
   762 				}
       
   763 
       
   764 				case PCW_WIDGET_PRESIDENT_NAME: {
       
   765 					const Player *p = GetPlayer(w->window_number);
       
   766 					WP(w, def_d).byte_1 = 0;
       
   767 					SetDParam(0, p->president_name_2);
       
   768 					ShowQueryString(p->president_name_1, STR_700B_PRESIDENT_S_NAME, 31, 94, w, CS_ALPHANUMERAL);
       
   769 					break;
       
   770 				}
       
   771 
       
   772 				case PCW_WIDGET_COMPANY_NAME: {
       
   773 					Player *p = GetPlayer(w->window_number);
       
   774 					WP(w,def_d).byte_1 = 1;
       
   775 					SetDParam(0, p->name_2);
       
   776 					ShowQueryString(p->name_1, STR_700A_COMPANY_NAME, 31, 150, w, CS_ALPHANUMERAL);
       
   777 					break;
       
   778 				}
       
   779 
       
   780 				case PCW_WIDGET_BUILD_VIEW_HQ: {
       
   781 					TileIndex tile = GetPlayer(w->window_number)->location_of_house;
       
   782 					if (tile == 0) {
       
   783 						if ((byte)w->window_number != _local_player)
       
   784 							return;
       
   785 						SetObjectToPlaceWnd(SPR_CURSOR_HQ, 1, w);
       
   786 						SetTileSelectSize(2, 2);
       
   787 						LowerWindowWidget(w, PCW_WIDGET_BUILD_VIEW_HQ);
       
   788 						InvalidateWidget(w, PCW_WIDGET_BUILD_VIEW_HQ);
       
   789 					} else {
       
   790 						ScrollMainWindowToTile(tile);
       
   791 					}
       
   792 					break;
       
   793 				}
       
   794 
       
   795 				case PCW_WIDGET_RELOCATE_HQ:
       
   796 					SetObjectToPlaceWnd(SPR_CURSOR_HQ, 1, w);
       
   797 					SetTileSelectSize(2, 2);
       
   798 					LowerWindowWidget(w, PCW_WIDGET_RELOCATE_HQ);
       
   799 					InvalidateWidget(w, PCW_WIDGET_RELOCATE_HQ);
       
   800 					break;
       
   801 
       
   802 				case PCW_WIDGET_BUY_SHARE:
       
   803 					DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_707B_CAN_T_BUY_25_SHARE_IN_THIS));
       
   804 					break;
       
   805 
       
   806 				case PCW_WIDGET_SELL_SHARE:
       
   807 					DoCommandP(0, w->window_number, 0, NULL, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_707C_CAN_T_SELL_25_SHARE_IN));
       
   808 					break;
       
   809 
       
   810 				#ifdef ENABLE_NETWORK
       
   811 				case PCW_WIDGET_COMPANY_PASSWORD:
       
   812 					if (w->window_number == _local_player) {
       
   813 						WP(w,def_d).byte_1 = 2;
       
   814 						ShowQueryString(BindCString(_network_player_info[_local_player].password),
       
   815 							STR_SET_COMPANY_PASSWORD, sizeof(_network_player_info[_local_player].password), 250, w, CS_ALPHANUMERAL);
       
   816 					}
       
   817 					break;
       
   818 				#endif /* ENABLE_NETWORK */
       
   819 			}
       
   820 			break;
       
   821 
       
   822 		case WE_MOUSELOOP:
       
   823 			/* redraw the window every now and then */
       
   824 			if ((++w->vscroll.pos & 0x1F) == 0) SetWindowDirty(w);
       
   825 			break;
       
   826 
       
   827 		case WE_PLACE_OBJ:
       
   828 			if (DoCommandP(e->we.place.tile, 0, 0, NULL, CMD_BUILD_COMPANY_HQ | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS)))
       
   829 				ResetObjectToPlace();
       
   830 				w->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; // this button can now behave as a normal push button
       
   831 				RaiseWindowButtons(w);
       
   832 			break;
       
   833 
       
   834 		case WE_ABORT_PLACE_OBJ:
       
   835 			RaiseWindowButtons(w);
       
   836 			break;
       
   837 
       
   838 		case WE_DESTROY:
       
   839 			DeleteWindowById(WC_PLAYER_FACE, w->window_number);
       
   840 			break;
       
   841 
       
   842 		case WE_ON_EDIT_TEXT: {
       
   843 			char *b = e->we.edittext.str;
       
   844 
       
   845 			// empty string is allowed for password
       
   846 			if (*b == '\0' && WP(w,def_d).byte_1 != 2) return;
       
   847 
       
   848 			_cmd_text = b;
       
   849 			switch (WP(w,def_d).byte_1) {
       
   850 				case 0: /* Change president name */
       
   851 					DoCommandP(0, 0, 0, NULL, CMD_CHANGE_PRESIDENT_NAME | CMD_MSG(STR_700D_CAN_T_CHANGE_PRESIDENT));
       
   852 					break;
       
   853 				case 1: /* Change company name */
       
   854 					DoCommandP(0, 0, 0, NULL, CMD_CHANGE_COMPANY_NAME | CMD_MSG(STR_700C_CAN_T_CHANGE_COMPANY_NAME));
       
   855 					break;
       
   856 				#ifdef ENABLE_NETWORK
       
   857 				case 2: /* Change company password */
       
   858 					if (*b == '\0') *b = '*'; // empty password is a '*' because of console argument
       
   859 					NetworkChangeCompanyPassword(1, &b);
       
   860 					break;
       
   861 				#endif /* ENABLE_NETWORK */
       
   862 			}
       
   863 			break;
       
   864 		}
       
   865 	}
       
   866 }
       
   867 
       
   868 
       
   869 static const WindowDesc _player_company_desc = {
       
   870 	WDP_AUTO, WDP_AUTO, 360, 170,
       
   871 	WC_COMPANY, 0,
       
   872 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
       
   873 	_player_company_widgets,
       
   874 	PlayerCompanyWndProc
       
   875 };
       
   876 
       
   877 void ShowPlayerCompany(PlayerID player)
       
   878 {
       
   879 	Window *w;
       
   880 
       
   881 	if (!IsValidPlayer(player)) return;
       
   882 
       
   883 	w = AllocateWindowDescFront(&_player_company_desc, player);
       
   884 	if (w != NULL) w->caption_color = w->window_number;
       
   885 }
       
   886 
       
   887 
       
   888 
       
   889 static void BuyCompanyWndProc(Window *w, WindowEvent *e)
       
   890 {
       
   891 	switch (e->event) {
       
   892 	case WE_PAINT: {
       
   893 		Player *p = GetPlayer(w->window_number);
       
   894 		SetDParam(0, p->name_1);
       
   895 		SetDParam(1, p->name_2);
       
   896 		DrawWindowWidgets(w);
       
   897 
       
   898 		DrawPlayerFace(p->face, p->player_color, 2, 16);
       
   899 
       
   900 		SetDParam(0, p->name_1);
       
   901 		SetDParam(1, p->name_2);
       
   902 		SetDParam(2, p->bankrupt_value);
       
   903 		DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238);
       
   904 		break;
       
   905 	}
       
   906 
       
   907 	case WE_CLICK:
       
   908 		switch (e->we.click.widget) {
       
   909 		case 3:
       
   910 			DeleteWindow(w);
       
   911 			break;
       
   912 		case 4: {
       
   913 			DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY));
       
   914 			break;
       
   915 		}
       
   916 		}
       
   917 		break;
       
   918 	}
       
   919 }
       
   920 
       
   921 static const Widget _buy_company_widgets[] = {
       
   922 {   WWT_CLOSEBOX,   RESIZE_NONE,     5,     0,    10,     0,    13, STR_00C5,              STR_018B_CLOSE_WINDOW},
       
   923 {    WWT_CAPTION,   RESIZE_NONE,     5,    11,   333,     0,    13, STR_00B3_MESSAGE_FROM, STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   924 {      WWT_PANEL,   RESIZE_NONE,     5,     0,   333,    14,   136, 0x0,                   STR_NULL},
       
   925 {    WWT_TEXTBTN,   RESIZE_NONE,     5,   148,   207,   117,   128, STR_00C9_NO,           STR_NULL},
       
   926 {    WWT_TEXTBTN,   RESIZE_NONE,     5,   218,   277,   117,   128, STR_00C8_YES,          STR_NULL},
       
   927 {   WIDGETS_END},
       
   928 };
       
   929 
       
   930 static const WindowDesc _buy_company_desc = {
       
   931 	153, 171, 334, 137,
       
   932 	WC_BUY_COMPANY,0,
       
   933 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
       
   934 	_buy_company_widgets,
       
   935 	BuyCompanyWndProc
       
   936 };
       
   937 
       
   938 
       
   939 void ShowBuyCompanyDialog(uint player)
       
   940 {
       
   941 	AllocateWindowDescFront(&_buy_company_desc, player);
       
   942 }
       
   943 
       
   944 /********** HIGHSCORE and ENDGAME windows */
       
   945 
       
   946 /* Always draw a maximized window and within there the centered background */
       
   947 static void SetupHighScoreEndWindow(Window *w, uint *x, uint *y)
       
   948 {
       
   949 	uint i;
       
   950 	// resize window to "full-screen"
       
   951 	w->width = _screen.width;
       
   952 	w->height = _screen.height;
       
   953 	w->widget[0].right = w->width - 1;
       
   954 	w->widget[0].bottom = w->height - 1;
       
   955 
       
   956 	DrawWindowWidgets(w);
       
   957 
       
   958 	/* Center Highscore/Endscreen background */
       
   959 	*x = max(0, (_screen.width  / 2) - (640 / 2));
       
   960 	*y = max(0, (_screen.height / 2) - (480 / 2));
       
   961 	for (i = 0; i < 10; i++) // the image is split into 10 50px high parts
       
   962 		DrawSprite(WP(w, highscore_d).background_img + i, *x, *y + (i * 50));
       
   963 }
       
   964 
       
   965 extern StringID EndGameGetPerformanceTitleFromValue(uint value);
       
   966 
       
   967 /* End game window shown at the end of the game */
       
   968 static void EndGameWndProc(Window *w, WindowEvent *e)
       
   969 {
       
   970 	switch (e->event) {
       
   971 	case WE_PAINT: {
       
   972 		const Player *p;
       
   973 		uint x, y;
       
   974 
       
   975 		SetupHighScoreEndWindow(w, &x, &y);
       
   976 
       
   977 		if (!IsValidPlayer(_local_player)) break;
       
   978 
       
   979 		p = GetPlayer(_local_player);
       
   980 		/* We need to get performance from last year because the image is shown
       
   981 		 * at the start of the new year when these things have already been copied */
       
   982 		if (WP(w, highscore_d).background_img == SPR_TYCOON_IMG2_BEGIN) { // Tycoon of the century \o/
       
   983 			SetDParam(0, p->president_name_1);
       
   984 			SetDParam(1, p->president_name_2);
       
   985 			SetDParam(2, p->name_1);
       
   986 			SetDParam(3, p->name_2);
       
   987 			SetDParam(4, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history));
       
   988 			DrawStringMultiCenter(x + (640 / 2), y + 107, STR_021C_OF_ACHIEVES_STATUS, 640);
       
   989 		} else {
       
   990 			SetDParam(0, p->name_1);
       
   991 			SetDParam(1, p->name_2);
       
   992 			SetDParam(2, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history));
       
   993 			DrawStringMultiCenter(x + (640 / 2), y + 157, STR_021B_ACHIEVES_STATUS, 640);
       
   994 		}
       
   995 	} break;
       
   996 	case WE_CLICK: /* Close the window (and show the highscore window) */
       
   997 		DeleteWindow(w);
       
   998 		break;
       
   999 	case WE_DESTROY: /* Show the highscore window when this one is closed */
       
  1000 		if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause
       
  1001 		ShowHighscoreTable(w->window_number, WP(w, highscore_d).rank);
       
  1002 		break;
       
  1003 	}
       
  1004 }
       
  1005 
       
  1006 static void HighScoreWndProc(Window *w, WindowEvent *e)
       
  1007 {
       
  1008 	switch (e->event) {
       
  1009 	case WE_PAINT: {
       
  1010 		const HighScore *hs = _highscore_table[w->window_number];
       
  1011 		uint x, y;
       
  1012 		uint8 i;
       
  1013 
       
  1014 		SetupHighScoreEndWindow(w, &x, &y);
       
  1015 
       
  1016 		SetDParam(0, _patches.ending_year);
       
  1017 		SetDParam(1, w->window_number + STR_6801_EASY);
       
  1018 		DrawStringMultiCenter(x + (640 / 2), y + 62, !_networking ? STR_0211_TOP_COMPANIES_WHO_REACHED : STR_TOP_COMPANIES_NETWORK_GAME, 500);
       
  1019 
       
  1020 		/* Draw Highscore peepz */
       
  1021 		for (i = 0; i < lengthof(_highscore_table[0]); i++) {
       
  1022 			SetDParam(0, i + 1);
       
  1023 			DrawString(x + 40, y + 140 + (i * 55), STR_0212, 0x10);
       
  1024 
       
  1025 			if (hs[i].company[0] != '\0') {
       
  1026 				uint16 colour = (WP(w, highscore_d).rank == (int8)i) ? 0x3 : 0x10; // draw new highscore in red
       
  1027 
       
  1028 				DoDrawString(hs[i].company, x + 71, y + 140 + (i * 55), colour);
       
  1029 				SetDParam(0, hs[i].title);
       
  1030 				SetDParam(1, hs[i].score);
       
  1031 				DrawString(x + 71, y + 160 + (i * 55), STR_HIGHSCORE_STATS, colour);
       
  1032 			}
       
  1033 		}
       
  1034 	} break;
       
  1035 
       
  1036 	case WE_CLICK: /* Onclick to close window, and in destroy event handle the rest */
       
  1037 		DeleteWindow(w);
       
  1038 		break;
       
  1039 
       
  1040 	case WE_DESTROY: /* Get back all the hidden windows */
       
  1041 		if (_game_mode != GM_MENU) ShowVitalWindows();
       
  1042 
       
  1043 		if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause
       
  1044 		break;
       
  1045 	}
       
  1046 	}
       
  1047 
       
  1048 static const Widget _highscore_widgets[] = {
       
  1049 {      WWT_PANEL, RESIZE_NONE, 16, 0, 640, 0, 480, 0x0, STR_NULL},
       
  1050 {   WIDGETS_END},
       
  1051 };
       
  1052 
       
  1053 static const WindowDesc _highscore_desc = {
       
  1054 	0, 0, 641, 481,
       
  1055 	WC_HIGHSCORE,0,
       
  1056 	0,
       
  1057 	_highscore_widgets,
       
  1058 	HighScoreWndProc
       
  1059 };
       
  1060 
       
  1061 static const WindowDesc _endgame_desc = {
       
  1062 	0, 0, 641, 481,
       
  1063 	WC_ENDSCREEN,0,
       
  1064 	0,
       
  1065 	_highscore_widgets,
       
  1066 	EndGameWndProc
       
  1067 };
       
  1068 
       
  1069 /* Show the highscore table for a given difficulty. When called from
       
  1070  * endgame ranking is set to the top5 element that was newly added
       
  1071  * and is thus highlighted */
       
  1072 void ShowHighscoreTable(int difficulty, int8 ranking)
       
  1073 {
       
  1074 	Window *w;
       
  1075 
       
  1076 	// pause game to show the chart
       
  1077 	if (!_networking) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
       
  1078 
       
  1079 	/* Close all always on-top windows to get a clean screen */
       
  1080 	if (_game_mode != GM_MENU) HideVitalWindows();
       
  1081 
       
  1082 	DeleteWindowByClass(WC_HIGHSCORE);
       
  1083 	w = AllocateWindowDesc(&_highscore_desc);
       
  1084 
       
  1085 	if (w != NULL) {
       
  1086 		MarkWholeScreenDirty();
       
  1087 		w->window_number = difficulty; // show highscore chart for difficulty...
       
  1088 		WP(w, highscore_d).background_img = SPR_HIGHSCORE_CHART_BEGIN; // which background to show
       
  1089 		WP(w, highscore_d).rank = ranking;
       
  1090 	}
       
  1091 }
       
  1092 
       
  1093 /* Show the endgame victory screen in 2050. Update the new highscore
       
  1094  * if it was high enough */
       
  1095 void ShowEndGameChart(void)
       
  1096 {
       
  1097 	Window *w;
       
  1098 
       
  1099 	/* Dedicated server doesn't need the highscore window */
       
  1100 	if (_network_dedicated) return;
       
  1101 	/* Pause in single-player to have a look at the highscore at your own leisure */
       
  1102 	if (!_networking) DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
       
  1103 
       
  1104 	HideVitalWindows();
       
  1105 	DeleteWindowByClass(WC_ENDSCREEN);
       
  1106 	w = AllocateWindowDesc(&_endgame_desc);
       
  1107 
       
  1108 	if (w != NULL) {
       
  1109 		MarkWholeScreenDirty();
       
  1110 
       
  1111 		WP(w, highscore_d).background_img = SPR_TYCOON_IMG1_BEGIN;
       
  1112 
       
  1113 		if (_local_player != PLAYER_SPECTATOR) {
       
  1114 			const Player *p = GetPlayer(_local_player);
       
  1115 			if (p->old_economy[0].performance_history == SCORE_MAX)
       
  1116 				WP(w, highscore_d).background_img = SPR_TYCOON_IMG2_BEGIN;
       
  1117 		}
       
  1118 
       
  1119 		/* In a network game show the endscores of the custom difficulty 'network' which is the last one
       
  1120 		 * as well as generate a TOP5 of that game, and not an all-time top5. */
       
  1121 		if (_networking) {
       
  1122 			w->window_number = lengthof(_highscore_table) - 1;
       
  1123 			WP(w, highscore_d).rank = SaveHighScoreValueNetwork();
       
  1124 		} else {
       
  1125 			// in single player _local player is always valid
       
  1126 			const Player *p = GetPlayer(_local_player);
       
  1127 			w->window_number = _opt.diff_level;
       
  1128 			WP(w, highscore_d).rank = SaveHighScoreValue(p);
       
  1129 		}
       
  1130 	}
       
  1131 }