src/network/network_gui.cpp
branchnoai
changeset 10645 8cbdb511a674
parent 10513 33cb70ff2f5d
child 10715 6bdf79ffb022
equal deleted inserted replaced
10644:6c4314786d68 10645:8cbdb511a674
    28 #include "../gfx_func.h"
    28 #include "../gfx_func.h"
    29 #include "../player_func.h"
    29 #include "../player_func.h"
    30 #include "../settings_type.h"
    30 #include "../settings_type.h"
    31 #include "../widgets/dropdown_func.h"
    31 #include "../widgets/dropdown_func.h"
    32 #include "../querystring_gui.h"
    32 #include "../querystring_gui.h"
       
    33 #include "../sortlist_type.h"
    33 
    34 
    34 #include "table/strings.h"
    35 #include "table/strings.h"
    35 #include "../table/sprites.h"
    36 #include "../table/sprites.h"
    36 
    37 
    37 #define BGC 5
    38 #define BGC 5
   316 				!sel->online ||
   317 				!sel->online ||
   317 				sel->info.grfconfig == NULL);
   318 				sel->info.grfconfig == NULL);
   318 
   319 
   319 		SetDParam(0, 0x00);
   320 		SetDParam(0, 0x00);
   320 		SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
   321 		SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
   321 		DrawWindowWidgets(this);
   322 		this->DrawWidgets();
   322 
   323 
   323 		/* Edit box to set player name */
   324 		/* Edit box to set player name */
   324 		this->DrawEditBox(NGWW_PLAYER);
   325 		this->DrawEditBox(NGWW_PLAYER);
   325 
   326 
   326 		DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
   327 		DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
   327 
   328 
   328 		/* Sort based on widgets: name, clients, compatibility */
   329 		/* Sort based on widgets: name, clients, compatibility */
   329 		switch (this->servers.sort_type) {
   330 		switch (this->servers.sort_type) {
   330 			case NGWW_NAME    - NGWW_NAME: DrawSortButtonState(this, NGWW_NAME,    arrow); break;
   331 			case NGWW_NAME    - NGWW_NAME: this->DrawSortButtonState(NGWW_NAME,    arrow); break;
   331 			case NGWW_CLIENTS - NGWW_NAME: DrawSortButtonState(this, NGWW_CLIENTS, arrow); break;
   332 			case NGWW_CLIENTS - NGWW_NAME: this->DrawSortButtonState(NGWW_CLIENTS, arrow); break;
   332 			case NGWW_INFO    - NGWW_NAME: DrawSortButtonState(this, NGWW_INFO,    arrow); break;
   333 			case NGWW_INFO    - NGWW_NAME: this->DrawSortButtonState(NGWW_INFO,    arrow); break;
   333 		}
   334 		}
   334 
   335 
   335 		uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
   336 		uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
   336 		int32 n = 0;
   337 		int32 n = 0;
   337 		int32 pos = this->vscroll.pos;
   338 		int32 pos = this->vscroll.pos;
   540 		if (data != 0) this->server = NULL;
   541 		if (data != 0) this->server = NULL;
   541 		this->servers.flags |= VL_REBUILD;
   542 		this->servers.flags |= VL_REBUILD;
   542 		this->SetDirty();
   543 		this->SetDirty();
   543 	}
   544 	}
   544 
   545 
   545 	virtual bool OnKeyPress(uint16 key, uint16 keycode)
   546 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
   546 	{
   547 	{
   547 		bool cont = true;
   548 		EventState state = ES_NOT_HANDLED;
   548 		if (this->field != NGWW_PLAYER) {
   549 		if (this->field != NGWW_PLAYER) {
   549 			if (this->server != NULL) {
   550 			if (this->server != NULL) {
   550 				if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
   551 				if (keycode == WKC_DELETE) { // Press 'delete' to remove servers
   551 					NetworkGameListRemoveItem(this->server);
   552 					NetworkGameListRemoveItem(this->server);
   552 					NetworkRebuildHostList();
   553 					NetworkRebuildHostList();
   553 					this->server = NULL;
   554 					this->server = NULL;
   554 				}
   555 				}
   555 			}
   556 			}
   556 			return cont;
   557 			return state;
   557 		}
   558 		}
   558 
   559 
   559 		if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, cont) == 1) return cont; // enter pressed
   560 		if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, state) == 1) return state; // enter pressed
   560 
   561 
   561 		/* The name is only allowed when it starts with a letter! */
   562 		/* The name is only allowed when it starts with a letter! */
   562 		if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
   563 		if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
   563 			ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
   564 			ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
   564 		} else {
   565 		} else {
   565 			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
   566 			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
   566 		}
   567 		}
   567 		return cont;
   568 		return state;
   568 	}
   569 	}
   569 
   570 
   570 	virtual void OnQueryTextFinished(char *str)
   571 	virtual void OnQueryTextFinished(char *str)
   571 	{
   572 	{
   572 		if (!StrEmpty(str)) {
   573 		if (!StrEmpty(str)) {
   639 static const WindowDesc _network_game_window_desc = {
   640 static const WindowDesc _network_game_window_desc = {
   640 	WDP_CENTER, WDP_CENTER, 450, 264, 550, 264,
   641 	WDP_CENTER, WDP_CENTER, 450, 264, 550, 264,
   641 	WC_NETWORK_WINDOW, WC_NONE,
   642 	WC_NETWORK_WINDOW, WC_NONE,
   642 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   643 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   643 	_network_game_window_widgets,
   644 	_network_game_window_widgets,
   644 	NULL,
       
   645 };
   645 };
   646 
   646 
   647 void ShowNetworkGameWindow()
   647 void ShowNetworkGameWindow()
   648 {
   648 {
   649 	static bool first = true;
   649 	static bool first = true;
   725 		SetDParam(1, _connection_types_dropdown[_network_advertise]);
   725 		SetDParam(1, _connection_types_dropdown[_network_advertise]);
   726 		SetDParam(2, _network_game_info.clients_max);
   726 		SetDParam(2, _network_game_info.clients_max);
   727 		SetDParam(3, _network_game_info.companies_max);
   727 		SetDParam(3, _network_game_info.companies_max);
   728 		SetDParam(4, _network_game_info.spectators_max);
   728 		SetDParam(4, _network_game_info.spectators_max);
   729 		SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
   729 		SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
   730 		DrawWindowWidgets(this);
   730 		this->DrawWidgets();
   731 
   731 
   732 		/* editbox to set game name */
   732 		/* editbox to set game name */
   733 		this->DrawEditBox(NSSW_GAMENAME);
   733 		this->DrawEditBox(NSSW_GAMENAME);
   734 
   734 
   735 		/* if password is set, draw red '*' next to 'Set password' button */
   735 		/* if password is set, draw red '*' next to 'Set password' button */
   889 	virtual void OnMouseLoop()
   889 	virtual void OnMouseLoop()
   890 	{
   890 	{
   891 		if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
   891 		if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
   892 	}
   892 	}
   893 
   893 
   894 	virtual bool OnKeyPress(uint16 key, uint16 keycode)
   894 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
   895 	{
   895 	{
   896 		bool cont = true;
   896 		EventState state = ES_NOT_HANDLED;
   897 		if (this->field == NSSW_GAMENAME) {
   897 		if (this->field == NSSW_GAMENAME) {
   898 			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, cont) == 1) return cont; // enter pressed
   898 			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == 1) return state; // enter pressed
   899 
   899 
   900 			ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
   900 			ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
   901 		}
   901 		}
   902 
   902 
   903 		return cont;
   903 		return state;
   904 	}
   904 	}
   905 
   905 
   906 	virtual void OnQueryTextFinished(char *str)
   906 	virtual void OnQueryTextFinished(char *str)
   907 	{
   907 	{
   908 		if (str == NULL) return;
   908 		if (str == NULL) return;
   974 static const WindowDesc _network_start_server_window_desc = {
   974 static const WindowDesc _network_start_server_window_desc = {
   975 	WDP_CENTER, WDP_CENTER, 420, 244, 420, 244,
   975 	WDP_CENTER, WDP_CENTER, 420, 244, 420, 244,
   976 	WC_NETWORK_WINDOW, WC_NONE,
   976 	WC_NETWORK_WINDOW, WC_NONE,
   977 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
   977 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
   978 	_network_start_server_window_widgets,
   978 	_network_start_server_window_widgets,
   979 	NULL,
       
   980 };
   979 };
   981 
   980 
   982 static void ShowNetworkStartServerWindow()
   981 static void ShowNetworkStartServerWindow()
   983 {
   982 {
   984 	DeleteWindowById(WC_NETWORK_WINDOW, 0);
   983 	DeleteWindowById(WC_NETWORK_WINDOW, 0);
  1034 		/* Cannot spectate if there are too many spectators */
  1033 		/* Cannot spectate if there are too many spectators */
  1035 		this->SetWidgetDisabledState(NLWW_SPECTATE, gi->spectators_on >= gi->spectators_max);
  1034 		this->SetWidgetDisabledState(NLWW_SPECTATE, gi->spectators_on >= gi->spectators_max);
  1036 
  1035 
  1037 		/* Draw window widgets */
  1036 		/* Draw window widgets */
  1038 		SetDParamStr(0, gi->server_name);
  1037 		SetDParamStr(0, gi->server_name);
  1039 		DrawWindowWidgets(this);
  1038 		this->DrawWidgets();
  1040 
  1039 
  1041 		/* Draw company list */
  1040 		/* Draw company list */
  1042 		pos = this->vscroll.pos;
  1041 		pos = this->vscroll.pos;
  1043 		while (pos < gi->companies_on) {
  1042 		while (pos < gi->companies_on) {
  1044 			byte company = NetworkLobbyFindCompanyIndex(pos);
  1043 			byte company = NetworkLobbyFindCompanyIndex(pos);
  1188 static const WindowDesc _network_lobby_window_desc = {
  1187 static const WindowDesc _network_lobby_window_desc = {
  1189 	WDP_CENTER, WDP_CENTER, 420, 235, 420, 235,
  1188 	WDP_CENTER, WDP_CENTER, 420, 235, 420, 235,
  1190 	WC_NETWORK_WINDOW, WC_NONE,
  1189 	WC_NETWORK_WINDOW, WC_NONE,
  1191 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
  1190 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
  1192 	_network_lobby_window_widgets,
  1191 	_network_lobby_window_widgets,
  1193 	NULL,
       
  1194 };
  1192 };
  1195 
  1193 
  1196 /* Show the networklobbywindow with the selected server
  1194 /* Show the networklobbywindow with the selected server
  1197  * @param ngl Selected game pointer which is passed to the new window */
  1195  * @param ngl Selected game pointer which is passed to the new window */
  1198 static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
  1196 static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
  1214 // Every action must be of this form
  1212 // Every action must be of this form
  1215 typedef void ClientList_Action_Proc(byte client_no);
  1213 typedef void ClientList_Action_Proc(byte client_no);
  1216 
  1214 
  1217 // Max 10 actions per client
  1215 // Max 10 actions per client
  1218 #define MAX_CLIENTLIST_ACTION 10
  1216 #define MAX_CLIENTLIST_ACTION 10
  1219 
       
  1220 // Some standard bullshit.. defines variables ;)
       
  1221 static void ClientListWndProc(Window *w, WindowEvent *e);
       
  1222 static void ClientListPopupWndProc(Window *w, WindowEvent *e);
       
  1223 static byte _selected_clientlist_item = 255;
       
  1224 static byte _selected_clientlist_y = 0;
       
  1225 static char _clientlist_action[MAX_CLIENTLIST_ACTION][50];
       
  1226 static ClientList_Action_Proc *_clientlist_proc[MAX_CLIENTLIST_ACTION];
       
  1227 
  1217 
  1228 enum {
  1218 enum {
  1229 	CLNWND_OFFSET = 16,
  1219 	CLNWND_OFFSET = 16,
  1230 	CLNWND_ROWSIZE = 10
  1220 	CLNWND_ROWSIZE = 10
  1231 };
  1221 };
  1242 static const Widget _client_list_popup_widgets[] = {
  1232 static const Widget _client_list_popup_widgets[] = {
  1243 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   99,     0,     0,     0, STR_NULL},
  1233 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   99,     0,     0,     0, STR_NULL},
  1244 {   WIDGETS_END},
  1234 {   WIDGETS_END},
  1245 };
  1235 };
  1246 
  1236 
  1247 static WindowDesc _client_list_desc = {
  1237 static const WindowDesc _client_list_desc = {
  1248 	WDP_AUTO, WDP_AUTO, 250, 1, 250, 1,
  1238 	WDP_AUTO, WDP_AUTO, 250, 1, 250, 1,
  1249 	WC_CLIENT_LIST, WC_NONE,
  1239 	WC_CLIENT_LIST, WC_NONE,
  1250 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
  1240 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
  1251 	_client_list_widgets,
  1241 	_client_list_widgets,
  1252 	ClientListWndProc
       
  1253 };
  1242 };
  1254 
  1243 
  1255 // Finds the Xth client-info that is active
  1244 // Finds the Xth client-info that is active
  1256 static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
  1245 static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
  1257 {
  1246 {
  1319 	/* No action ;) */
  1308 	/* No action ;) */
  1320 }
  1309 }
  1321 
  1310 
  1322 
  1311 
  1323 
  1312 
  1324 /**
  1313 struct NetworkClientListPopupWindow : Window {
  1325  * An action is clicked! What do we do?
  1314 	int sel_index;
  1326  */
  1315 	int client_no;
  1327 static void HandleClientListPopupClick(byte index, byte clientno)
  1316 	char action[MAX_CLIENTLIST_ACTION][50];
  1328 {
  1317 	ClientList_Action_Proc *proc[MAX_CLIENTLIST_ACTION];
  1329 	/* A click on the Popup of the ClientList.. handle the command */
  1318 
  1330 	if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) {
  1319 	NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) :
  1331 		_clientlist_proc[index](clientno);
  1320 			Window(x, y, 150, 100, WC_TOOLBAR_MENU, widgets),
  1332 	}
  1321 			sel_index(0), client_no(client_no)
  1333 }
  1322 	{
  1334 
  1323 		/*
  1335 /**
  1324 		 * Fill the actions this client has.
  1336  * Finds the amount of clients and set the height correct
  1325 		 * Watch is, max 50 chars long!
  1337  */
  1326 		 */
  1338 static bool CheckClientListHeight(Window *w)
  1327 
  1339 {
  1328 		const NetworkClientInfo *ci = NetworkFindClientInfo(client_no);
  1340 	int num = 0;
  1329 
  1341 	const NetworkClientInfo *ci;
  1330 		int i = 0;
  1342 
  1331 		if (_network_own_client_index != ci->client_index) {
  1343 	/* Should be replaced with a loop through all clients */
  1332 			GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(this->action[i]));
  1344 	FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
  1333 			this->proc[i++] = &ClientList_SpeakToClient;
  1345 		num++;
  1334 		}
  1346 	}
  1335 
  1347 
  1336 		if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) {
  1348 	num *= CLNWND_ROWSIZE;
  1337 			GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(this->action[i]));
  1349 
  1338 			this->proc[i++] = &ClientList_SpeakToCompany;
  1350 	/* If height is changed */
  1339 		}
  1351 	if (w->height != CLNWND_OFFSET + num + 1) {
  1340 		GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(this->action[i]));
  1352 		// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
  1341 		this->proc[i++] = &ClientList_SpeakToAll;
  1353 		w->SetDirty();
  1342 
  1354 		w->widget[3].bottom = w->widget[3].top + num + 2;
  1343 		if (_network_own_client_index != ci->client_index) {
  1355 		w->height = CLNWND_OFFSET + num + 1;
  1344 			/* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */
  1356 		w->SetDirty();
  1345 			if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) {
  1357 		return false;
  1346 				GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i]));
  1358 	}
  1347 				this->proc[i++] = &ClientList_GiveMoney;
  1359 	return true;
  1348 			}
  1360 }
  1349 		}
  1361 
  1350 
  1362 /**
  1351 		/* A server can kick clients (but not himself) */
  1363  * Finds the amount of actions in the popup and set the height correct
  1352 		if (_network_server && _network_own_client_index != ci->client_index) {
  1364  */
  1353 			GetString(this->action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(this->action[i]));
  1365 static uint ClientListPopupHeight()
  1354 			this->proc[i++] = &ClientList_Kick;
  1366 {
  1355 
  1367 	int num = 0;
  1356 			sprintf(this->action[i],"Ban"); // XXX GetString?
  1368 
  1357 			this->proc[i++] = &ClientList_Ban;
  1369 	// Find the amount of actions
  1358 		}
  1370 	for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
  1359 
  1371 		if (_clientlist_action[i][0] == '\0') continue;
  1360 		if (i == 0) {
  1372 		if (_clientlist_proc[i] == NULL) continue;
  1361 			GetString(this->action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(this->action[i]));
  1373 		num++;
  1362 			this->proc[i++] = &ClientList_None;
  1374 	}
  1363 		}
  1375 
  1364 
  1376 	num *= CLNWND_ROWSIZE;
  1365 		/* Calculate the height */
  1377 
  1366 		int h = ClientListPopupHeight();
  1378 	return num + 1;
  1367 
  1379 }
  1368 		/* Allocate the popup */
       
  1369 		this->widget[0].bottom = this->widget[0].top + h;
       
  1370 		this->widget[0].right = this->widget[0].left + 150;
       
  1371 
       
  1372 		this->flags4 &= ~WF_WHITE_BORDER_MASK;
       
  1373 
       
  1374 		this->FindWindowPlacementAndResize(150, h + 1);
       
  1375 	}
       
  1376 
       
  1377 	/**
       
  1378 	 * An action is clicked! What do we do?
       
  1379 	 */
       
  1380 	void HandleClientListPopupClick(byte index)
       
  1381 	{
       
  1382 		/* A click on the Popup of the ClientList.. handle the command */
       
  1383 		if (index < MAX_CLIENTLIST_ACTION && this->proc[index] != NULL) {
       
  1384 			this->proc[index](this->client_no);
       
  1385 		}
       
  1386 	}
       
  1387 
       
  1388 	/**
       
  1389 	 * Finds the amount of actions in the popup and set the height correct
       
  1390 	 */
       
  1391 	uint ClientListPopupHeight()
       
  1392 	{
       
  1393 		int num = 0;
       
  1394 
       
  1395 		// Find the amount of actions
       
  1396 		for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
       
  1397 			if (this->action[i][0] == '\0') continue;
       
  1398 			if (this->proc[i] == NULL) continue;
       
  1399 			num++;
       
  1400 		}
       
  1401 
       
  1402 		num *= CLNWND_ROWSIZE;
       
  1403 
       
  1404 		return num + 1;
       
  1405 	}
       
  1406 
       
  1407 
       
  1408 	virtual void OnPaint()
       
  1409 	{
       
  1410 		this->DrawWidgets();
       
  1411 
       
  1412 		/* Draw the actions */
       
  1413 		int sel = this->sel_index;
       
  1414 		int y = 1;
       
  1415 		for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) {
       
  1416 			if (this->action[i][0] == '\0') continue;
       
  1417 			if (this->proc[i] == NULL) continue;
       
  1418 
       
  1419 			TextColour colour;
       
  1420 			if (sel-- == 0) { // Selected item, highlight it
       
  1421 				GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
       
  1422 				colour = TC_WHITE;
       
  1423 			} else {
       
  1424 				colour = TC_BLACK;
       
  1425 			}
       
  1426 
       
  1427 			DoDrawString(this->action[i], 4, y, colour);
       
  1428 		}
       
  1429 	}
       
  1430 
       
  1431 	virtual void OnMouseLoop()
       
  1432 	{
       
  1433 		/* We selected an action */
       
  1434 		int index = (_cursor.pos.y - this->top) / CLNWND_ROWSIZE;
       
  1435 
       
  1436 		if (_left_button_down) {
       
  1437 			if (index == -1 || index == this->sel_index) return;
       
  1438 
       
  1439 			this->sel_index = index;
       
  1440 			this->SetDirty();
       
  1441 		} else {
       
  1442 			if (index >= 0 && _cursor.pos.y >= this->top) {
       
  1443 				HandleClientListPopupClick(index);
       
  1444 			}
       
  1445 
       
  1446 			DeleteWindowById(WC_TOOLBAR_MENU, 0);
       
  1447 		}
       
  1448 	}
       
  1449 };
  1380 
  1450 
  1381 /**
  1451 /**
  1382  * Show the popup (action list)
  1452  * Show the popup (action list)
  1383  */
  1453  */
  1384 static Window *PopupClientList(Window *w, int client_no, int x, int y)
  1454 static void PopupClientList(int client_no, int x, int y)
  1385 {
  1455 {
  1386 	int i;
       
  1387 	const NetworkClientInfo *ci;
       
  1388 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
  1456 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
  1389 
  1457 
  1390 	/* Clean the current actions */
  1458 	if (NetworkFindClientInfo(client_no) == NULL) return;
  1391 	for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
  1459 
  1392 		_clientlist_action[i][0] = '\0';
  1460 	new NetworkClientListPopupWindow(x, y, _client_list_popup_widgets, client_no);
  1393 		_clientlist_proc[i] = NULL;
       
  1394 	}
       
  1395 
       
  1396 	/*
       
  1397 	 * Fill the actions this client has.
       
  1398 	 * Watch is, max 50 chars long!
       
  1399 	 */
       
  1400 
       
  1401 	ci = NetworkFindClientInfo(client_no);
       
  1402 	if (ci == NULL) return NULL;
       
  1403 
       
  1404 	i = 0;
       
  1405 	if (_network_own_client_index != ci->client_index) {
       
  1406 		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i]));
       
  1407 		_clientlist_proc[i++] = &ClientList_SpeakToClient;
       
  1408 	}
       
  1409 
       
  1410 	if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) {
       
  1411 		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i]));
       
  1412 		_clientlist_proc[i++] = &ClientList_SpeakToCompany;
       
  1413 	}
       
  1414 	GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i]));
       
  1415 	_clientlist_proc[i++] = &ClientList_SpeakToAll;
       
  1416 
       
  1417 	if (_network_own_client_index != ci->client_index) {
       
  1418 		/* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */
       
  1419 		if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) {
       
  1420 			GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i]));
       
  1421 			_clientlist_proc[i++] = &ClientList_GiveMoney;
       
  1422 		}
       
  1423 	}
       
  1424 
       
  1425 	/* A server can kick clients (but not himself) */
       
  1426 	if (_network_server && _network_own_client_index != ci->client_index) {
       
  1427 		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i]));
       
  1428 		_clientlist_proc[i++] = &ClientList_Kick;
       
  1429 
       
  1430 		sprintf(_clientlist_action[i],"Ban"); // XXX GetString?
       
  1431 		_clientlist_proc[i++] = &ClientList_Ban;
       
  1432 	}
       
  1433 
       
  1434 	if (i == 0) {
       
  1435 		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i]));
       
  1436 		_clientlist_proc[i++] = &ClientList_None;
       
  1437 	}
       
  1438 
       
  1439 	/* Calculate the height */
       
  1440 	int h = ClientListPopupHeight();
       
  1441 
       
  1442 	/* Allocate the popup */
       
  1443 	w = new Window(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
       
  1444 	w->widget[0].bottom = w->widget[0].top + h;
       
  1445 	w->widget[0].right = w->widget[0].left + 150;
       
  1446 
       
  1447 	w->flags4 &= ~WF_WHITE_BORDER_MASK;
       
  1448 	WP(w, menu_d).item_count = 0;
       
  1449 	// Save our client
       
  1450 	WP(w, menu_d).main_button = client_no;
       
  1451 	WP(w, menu_d).sel_index = 0;
       
  1452 
       
  1453 	return w;
       
  1454 }
       
  1455 
       
  1456 /** Main handle for the client popup list
       
  1457  * uses menu_d WP macro */
       
  1458 static void ClientListPopupWndProc(Window *w, WindowEvent *e)
       
  1459 {
       
  1460 	switch (e->event) {
       
  1461 		case WE_PAINT: {
       
  1462 			DrawWindowWidgets(w);
       
  1463 
       
  1464 			/* Draw the actions */
       
  1465 			int sel = WP(w, menu_d).sel_index;
       
  1466 			int y = 1;
       
  1467 			for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) {
       
  1468 				if (_clientlist_action[i][0] == '\0') continue;
       
  1469 				if (_clientlist_proc[i] == NULL) continue;
       
  1470 
       
  1471 				TextColour colour;
       
  1472 				if (sel-- == 0) { // Selected item, highlight it
       
  1473 					GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
       
  1474 					colour = TC_WHITE;
       
  1475 				} else {
       
  1476 					colour = TC_BLACK;
       
  1477 				}
       
  1478 
       
  1479 				DoDrawString(_clientlist_action[i], 4, y, colour);
       
  1480 			}
       
  1481 		} break;
       
  1482 
       
  1483 		case WE_MOUSELOOP: {
       
  1484 			/* We selected an action */
       
  1485 			int index = (_cursor.pos.y - w->top) / CLNWND_ROWSIZE;
       
  1486 
       
  1487 			if (_left_button_down) {
       
  1488 				if (index == -1 || index == WP(w, menu_d).sel_index) return;
       
  1489 
       
  1490 				WP(w, menu_d).sel_index = index;
       
  1491 				w->SetDirty();
       
  1492 			} else {
       
  1493 				if (index >= 0 && _cursor.pos.y >= w->top) {
       
  1494 					HandleClientListPopupClick(index, WP(w, menu_d).main_button);
       
  1495 				}
       
  1496 
       
  1497 				DeleteWindowById(WC_TOOLBAR_MENU, 0);
       
  1498 			}
       
  1499 		} break;
       
  1500 	}
       
  1501 }
  1461 }
  1502 
  1462 
  1503 /**
  1463 /**
  1504  * Main handle for clientlist
  1464  * Main handle for clientlist
  1505  */
  1465  */
  1506 static void ClientListWndProc(Window *w, WindowEvent *e)
  1466 struct NetworkClientListWindow : Window
  1507 {
  1467 {
  1508 	switch (e->event) {
  1468 	byte selected_item;
  1509 		case WE_PAINT: {
  1469 	byte selected_y;
  1510 			NetworkClientInfo *ci;
  1470 
  1511 			int i = 0;
  1471 	NetworkClientListWindow(const WindowDesc *desc, WindowNumber window_number) :
  1512 
  1472 			Window(desc, window_number),
  1513 			/* Check if we need to reset the height */
  1473 			selected_item(0),
  1514 			if (!CheckClientListHeight(w)) break;
  1474 			selected_y(255)
  1515 
  1475 	{
  1516 			DrawWindowWidgets(w);
  1476 		this->FindWindowPlacementAndResize(desc);
  1517 
  1477 	}
  1518 			int y = CLNWND_OFFSET;
  1478 
  1519 
  1479 	/**
  1520 			FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
  1480 	 * Finds the amount of clients and set the height correct
  1521 				TextColour colour;
  1481 	 */
  1522 				if (_selected_clientlist_item == i++) { // Selected item, highlight it
  1482 	bool CheckClientListHeight()
  1523 					GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
  1483 	{
  1524 					colour = TC_WHITE;
  1484 		int num = 0;
  1525 				} else {
  1485 		const NetworkClientInfo *ci;
  1526 					colour = TC_BLACK;
  1486 
  1527 				}
  1487 		/* Should be replaced with a loop through all clients */
  1528 
  1488 		FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
  1529 				if (ci->client_index == NETWORK_SERVER_INDEX) {
  1489 			num++;
  1530 					DrawString(4, y, STR_NETWORK_SERVER, colour);
  1490 		}
  1531 				} else {
  1491 
  1532 					DrawString(4, y, STR_NETWORK_CLIENT, colour);
  1492 		num *= CLNWND_ROWSIZE;
  1533 				}
  1493 
  1534 
  1494 		/* If height is changed */
  1535 				/* Filter out spectators */
  1495 		if (this->height != CLNWND_OFFSET + num + 1) {
  1536 				if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1);
  1496 			// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
  1537 
  1497 			this->SetDirty();
  1538 				DoDrawString(ci->client_name, 81, y, colour);
  1498 			this->widget[3].bottom = this->widget[3].top + num + 2;
  1539 
  1499 			this->height = CLNWND_OFFSET + num + 1;
  1540 				y += CLNWND_ROWSIZE;
  1500 			this->SetDirty();
       
  1501 			return false;
       
  1502 		}
       
  1503 		return true;
       
  1504 	}
       
  1505 
       
  1506 	virtual void OnPaint()
       
  1507 	{
       
  1508 		NetworkClientInfo *ci;
       
  1509 		int i = 0;
       
  1510 
       
  1511 		/* Check if we need to reset the height */
       
  1512 		if (!this->CheckClientListHeight()) return;
       
  1513 
       
  1514 		this->DrawWidgets();
       
  1515 
       
  1516 		int y = CLNWND_OFFSET;
       
  1517 
       
  1518 		FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
       
  1519 			TextColour colour;
       
  1520 			if (this->selected_item == i++) { // Selected item, highlight it
       
  1521 				GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
       
  1522 				colour = TC_WHITE;
       
  1523 			} else {
       
  1524 				colour = TC_BLACK;
  1541 			}
  1525 			}
  1542 		} break;
  1526 
  1543 
  1527 			if (ci->client_index == NETWORK_SERVER_INDEX) {
  1544 		case WE_CLICK:
  1528 				DrawString(4, y, STR_NETWORK_SERVER, colour);
  1545 			/* Show the popup with option */
  1529 			} else {
  1546 			if (_selected_clientlist_item != 255) {
  1530 				DrawString(4, y, STR_NETWORK_CLIENT, colour);
  1547 				PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top);
       
  1548 			}
  1531 			}
  1549 			break;
  1532 
  1550 
  1533 			/* Filter out spectators */
  1551 		case WE_MOUSEOVER:
  1534 			if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1);
  1552 			/* -1 means we left the current window */
  1535 
  1553 			if (e->we.mouseover.pt.y == -1) {
  1536 			DoDrawString(ci->client_name, 81, y, colour);
  1554 				_selected_clientlist_y = 0;
  1537 
  1555 				_selected_clientlist_item = 255;
  1538 			y += CLNWND_ROWSIZE;
  1556 				w->SetDirty();
  1539 		}
  1557 				break;
  1540 	}
  1558 			}
  1541 
  1559 			/* It did not change.. no update! */
  1542 	virtual void OnClick(Point pt, int widget)
  1560 			if (e->we.mouseover.pt.y == _selected_clientlist_y) break;
  1543 	{
  1561 
  1544 		/* Show the popup with option */
  1562 			/* Find the new selected item (if any) */
  1545 		if (this->selected_item != 255) {
  1563 			_selected_clientlist_y = e->we.mouseover.pt.y;
  1546 			PopupClientList(this->selected_item, pt.x + this->left, pt.y + this->top);
  1564 			if (e->we.mouseover.pt.y > CLNWND_OFFSET) {
  1547 		}
  1565 				_selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
  1548 	}
  1566 			} else {
  1549 
  1567 				_selected_clientlist_item = 255;
  1550 	virtual void OnMouseOver(Point pt, int widget)
  1568 			}
  1551 	{
  1569 
  1552 		/* -1 means we left the current window */
  1570 			/* Repaint */
  1553 		if (pt.y == -1) {
  1571 			w->SetDirty();
  1554 			this->selected_y = 0;
  1572 			break;
  1555 			this->selected_item = 255;
  1573 
  1556 			this->SetDirty();
  1574 		case WE_DESTROY: case WE_CREATE:
  1557 			return;
  1575 			/* When created or destroyed, data is reset */
  1558 		}
  1576 			_selected_clientlist_item = 255;
  1559 		/* It did not change.. no update! */
  1577 			_selected_clientlist_y = 0;
  1560 		if (pt.y == this->selected_y) return;
  1578 			break;
  1561 
  1579 	}
  1562 		/* Find the new selected item (if any) */
  1580 }
  1563 		this->selected_y = pt.y;
       
  1564 		if (pt.y > CLNWND_OFFSET) {
       
  1565 			this->selected_item = (pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
       
  1566 		} else {
       
  1567 			this->selected_item = 255;
       
  1568 		}
       
  1569 
       
  1570 		/* Repaint */
       
  1571 		this->SetDirty();
       
  1572 	}
       
  1573 };
  1581 
  1574 
  1582 void ShowClientList()
  1575 void ShowClientList()
  1583 {
  1576 {
  1584 	AllocateWindowDescFront<Window>(&_client_list_desc, 0);
  1577 	AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
  1585 }
  1578 }
  1586 
  1579 
  1587 
  1580 
  1588 static NetworkPasswordType pw_type;
  1581 static NetworkPasswordType pw_type;
  1589 
  1582 
  1599 		case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
  1592 		case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
  1600 	}
  1593 	}
  1601 	ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
  1594 	ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
  1602 }
  1595 }
  1603 
  1596 
  1604 
  1597 struct NetworkJoinStatusWindow : Window {
  1605 static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e)
  1598 	NetworkJoinStatusWindow(const WindowDesc *desc) : Window(desc)
  1606 {
  1599 	{
  1607 	switch (e->event) {
  1600 		this->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
  1608 		case WE_PAINT: {
  1601 	}
  1609 			uint8 progress; // used for progress bar
  1602 
  1610 			DrawWindowWidgets(w);
  1603 	virtual void OnPaint()
  1611 
  1604 	{
  1612 			DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, TC_GREY);
  1605 		uint8 progress; // used for progress bar
  1613 			switch (_network_join_status) {
  1606 		this->DrawWidgets();
  1614 				case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
  1607 
  1615 				case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
  1608 		DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, TC_GREY);
  1616 					progress = 10; // first two stages 10%
  1609 		switch (_network_join_status) {
  1617 					break;
  1610 			case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
  1618 				case NETWORK_JOIN_STATUS_WAITING:
  1611 			case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
  1619 					SetDParam(0, _network_join_waiting);
  1612 				progress = 10; // first two stages 10%
  1620 					DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, TC_GREY);
  1613 				break;
  1621 					progress = 15; // third stage is 15%
  1614 			case NETWORK_JOIN_STATUS_WAITING:
  1622 					break;
  1615 				SetDParam(0, _network_join_waiting);
  1623 				case NETWORK_JOIN_STATUS_DOWNLOADING:
  1616 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, TC_GREY);
  1624 					SetDParam(0, _network_join_kbytes);
  1617 				progress = 15; // third stage is 15%
  1625 					SetDParam(1, _network_join_kbytes_total);
  1618 				break;
  1626 					DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, TC_GREY);
  1619 			case NETWORK_JOIN_STATUS_DOWNLOADING:
  1627 					/* Fallthrough */
  1620 				SetDParam(0, _network_join_kbytes);
  1628 				default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
  1621 				SetDParam(1, _network_join_kbytes_total);
  1629 					progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
  1622 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, TC_GREY);
  1630 			}
  1623 				/* Fallthrough */
  1631 
  1624 			default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
  1632 			/* Draw nice progress bar :) */
  1625 				progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
  1633 			DrawFrameRect(20, 18, (int)((w->width - 20) * progress / 100), 28, 10, FR_NONE);
  1626 		}
  1634 		} break;
  1627 
  1635 
  1628 		/* Draw nice progress bar :) */
  1636 		case WE_CLICK:
  1629 		DrawFrameRect(20, 18, (int)((this->width - 20) * progress / 100), 28, 10, FR_NONE);
  1637 			if (e->we.click.widget == 2) { //Disconnect button
  1630 	}
  1638 				NetworkDisconnect();
  1631 
  1639 				SwitchMode(SM_MENU);
  1632 	virtual void OnClick(Point pt, int widget)
  1640 				ShowNetworkGameWindow();
  1633 	{
  1641 			}
  1634 		if (widget == 2) { //Disconnect button
  1642 			break;
  1635 			NetworkDisconnect();
  1643 
  1636 			SwitchMode(SM_MENU);
  1644 		case WE_ON_EDIT_TEXT:
  1637 			ShowNetworkGameWindow();
  1645 			if (StrEmpty(e->we.edittext.str)) {
  1638 		}
  1646 				NetworkDisconnect();
  1639 	}
  1647 				ShowNetworkGameWindow();
  1640 
  1648 			} else {
  1641 	virtual void OnQueryTextFinished(char *str)
  1649 				SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, e->we.edittext.str);
  1642 	{
  1650 			}
  1643 		if (StrEmpty(str)) {
  1651 			break;
  1644 			NetworkDisconnect();
  1652 	}
  1645 			ShowNetworkGameWindow();
  1653 }
  1646 		} else {
       
  1647 			SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, str);
       
  1648 		}
       
  1649 	}
       
  1650 };
  1654 
  1651 
  1655 static const Widget _network_join_status_window_widget[] = {
  1652 static const Widget _network_join_status_window_widget[] = {
  1656 {    WWT_CAPTION,   RESIZE_NONE,    14,     0,   249,     0,    13, STR_NETWORK_CONNECTING, STR_018C_WINDOW_TITLE_DRAG_THIS},
  1653 {    WWT_CAPTION,   RESIZE_NONE,    14,     0,   249,     0,    13, STR_NETWORK_CONNECTING, STR_018C_WINDOW_TITLE_DRAG_THIS},
  1657 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   249,    14,    84, 0x0,                    STR_NULL},
  1654 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   249,    14,    84, 0x0,                    STR_NULL},
  1658 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    75,   175,    69,    80, STR_NETWORK_DISCONNECT, STR_NULL},
  1655 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    75,   175,    69,    80, STR_NETWORK_DISCONNECT, STR_NULL},
  1662 static const WindowDesc _network_join_status_window_desc = {
  1659 static const WindowDesc _network_join_status_window_desc = {
  1663 	WDP_CENTER, WDP_CENTER, 250, 85, 250, 85,
  1660 	WDP_CENTER, WDP_CENTER, 250, 85, 250, 85,
  1664 	WC_NETWORK_STATUS_WINDOW, WC_NONE,
  1661 	WC_NETWORK_STATUS_WINDOW, WC_NONE,
  1665 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
  1662 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
  1666 	_network_join_status_window_widget,
  1663 	_network_join_status_window_widget,
  1667 	NetworkJoinStatusWindowWndProc,
       
  1668 };
  1664 };
  1669 
  1665 
  1670 void ShowJoinStatusWindow()
  1666 void ShowJoinStatusWindow()
  1671 {
  1667 {
  1672 	DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
  1668 	DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
  1673 	Window *w = new Window(&_network_join_status_window_desc);
  1669 	new NetworkJoinStatusWindow(&_network_join_status_window_desc);
  1674 	/* Parent the status window to the lobby */
       
  1675 	if (w != NULL) w->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
       
  1676 }
  1670 }
  1677 
  1671 
  1678 static void SendChat(const char *buf, DestType type, int dest)
  1672 static void SendChat(const char *buf, DestType type, int dest)
  1679 {
  1673 {
  1680 	if (StrEmpty(buf)) return;
  1674 	if (StrEmpty(buf)) return;
  1851 			STR_NETWORK_CHAT_ALL_CAPTION,
  1845 			STR_NETWORK_CHAT_ALL_CAPTION,
  1852 			STR_NETWORK_CHAT_COMPANY_CAPTION,
  1846 			STR_NETWORK_CHAT_COMPANY_CAPTION,
  1853 			STR_NETWORK_CHAT_CLIENT_CAPTION
  1847 			STR_NETWORK_CHAT_CLIENT_CAPTION
  1854 		};
  1848 		};
  1855 
  1849 
  1856 		DrawWindowWidgets(this);
  1850 		this->DrawWidgets();
  1857 
  1851 
  1858 		assert((uint)this->dtype < lengthof(chat_captions));
  1852 		assert((uint)this->dtype < lengthof(chat_captions));
  1859 		DrawStringRightAligned(this->widget[2].left - 2, this->widget[2].top + 1, chat_captions[this->dtype], TC_BLACK);
  1853 		DrawStringRightAligned(this->widget[2].left - 2, this->widget[2].top + 1, chat_captions[this->dtype], TC_BLACK);
  1860 		this->DrawEditBox(2);
  1854 		this->DrawEditBox(2);
  1861 	}
  1855 	}
  1877 	virtual void OnMouseLoop()
  1871 	virtual void OnMouseLoop()
  1878 	{
  1872 	{
  1879 		this->HandleEditBox(2);
  1873 		this->HandleEditBox(2);
  1880 	}
  1874 	}
  1881 
  1875 
  1882 	virtual bool OnKeyPress(uint16 key, uint16 keycode)
  1876 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
  1883 	{
  1877 	{
  1884 		bool cont = true;
  1878 		EventState state = ES_NOT_HANDLED;
  1885 		if (keycode == WKC_TAB) {
  1879 		if (keycode == WKC_TAB) {
  1886 			ChatTabCompletion();
  1880 			ChatTabCompletion();
  1887 		} else {
  1881 		} else {
  1888 			_chat_tab_completion_active = false;
  1882 			_chat_tab_completion_active = false;
  1889 			switch (this->HandleEditBoxKey(2, key, keycode, cont)) {
  1883 			switch (this->HandleEditBoxKey(2, key, keycode, state)) {
  1890 				case 1: /* Return */
  1884 				case 1: /* Return */
  1891 					SendChat(this->text.buf, this->dtype, this->dest);
  1885 					SendChat(this->text.buf, this->dtype, this->dest);
  1892 				/* FALLTHROUGH */
  1886 				/* FALLTHROUGH */
  1893 				case 2: /* Escape */ delete this; break;
  1887 				case 2: /* Escape */ delete this; break;
  1894 			}
  1888 			}
  1895 		}
  1889 		}
  1896 		return cont;
  1890 		return state;
  1897 	}
  1891 	}
  1898 };
  1892 };
  1899 
  1893 
  1900 static const Widget _chat_window_widgets[] = {
  1894 static const Widget _chat_window_widgets[] = {
  1901 {   WWT_CLOSEBOX, RESIZE_NONE,  14,   0,  10,  0, 13, STR_00C5,                  STR_018B_CLOSE_WINDOW},
  1895 {   WWT_CLOSEBOX, RESIZE_NONE,  14,   0,  10,  0, 13, STR_00C5,                  STR_018B_CLOSE_WINDOW},
  1908 static const WindowDesc _chat_window_desc = {
  1902 static const WindowDesc _chat_window_desc = {
  1909 	WDP_CENTER, -26, 320, 14, 640, 14, // x, y, width, height
  1903 	WDP_CENTER, -26, 320, 14, 640, 14, // x, y, width, height
  1910 	WC_SEND_NETWORK_MSG, WC_NONE,
  1904 	WC_SEND_NETWORK_MSG, WC_NONE,
  1911 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
  1905 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
  1912 	_chat_window_widgets,
  1906 	_chat_window_widgets,
  1913 	NULL
       
  1914 };
  1907 };
  1915 
  1908 
  1916 void ShowNetworkChatQueryWindow(DestType type, int dest)
  1909 void ShowNetworkChatQueryWindow(DestType type, int dest)
  1917 {
  1910 {
  1918 	DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
  1911 	DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
  1930 	NCPWW_CANCEL,                   ///< Close the window without changing anything
  1923 	NCPWW_CANCEL,                   ///< Close the window without changing anything
  1931 	NCPWW_OK,                       ///< Safe the password etc.
  1924 	NCPWW_OK,                       ///< Safe the password etc.
  1932 };
  1925 };
  1933 
  1926 
  1934 struct NetworkCompanyPasswordWindow : public QueryStringBaseWindow {
  1927 struct NetworkCompanyPasswordWindow : public QueryStringBaseWindow {
  1935 	NetworkCompanyPasswordWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
  1928 	NetworkCompanyPasswordWindow(const WindowDesc *desc, Window *parent) : QueryStringBaseWindow(desc)
  1936 	{
  1929 	{
       
  1930 		this->parent = parent;
  1937 		this->afilter = CS_ALPHANUMERAL;
  1931 		this->afilter = CS_ALPHANUMERAL;
  1938 		InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
  1932 		InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
  1939 
  1933 
  1940 		this->FindWindowPlacementAndResize(desc);
  1934 		this->FindWindowPlacementAndResize(desc);
  1941 	}
  1935 	}
  1952 		NetworkChangeCompanyPassword(1, &password);
  1946 		NetworkChangeCompanyPassword(1, &password);
  1953 	}
  1947 	}
  1954 
  1948 
  1955 	virtual void OnPaint()
  1949 	virtual void OnPaint()
  1956 	{
  1950 	{
  1957 		DrawWindowWidgets(this);
  1951 		this->DrawWidgets();
  1958 		this->DrawEditBox(4);
  1952 		this->DrawEditBox(4);
  1959 	}
  1953 	}
  1960 
  1954 
  1961 	virtual void OnClick(Point pt, int widget)
  1955 	virtual void OnClick(Point pt, int widget)
  1962 	{
  1956 	{
  1983 	virtual void OnMouseLoop()
  1977 	virtual void OnMouseLoop()
  1984 	{
  1978 	{
  1985 		this->HandleEditBox(4);
  1979 		this->HandleEditBox(4);
  1986 	}
  1980 	}
  1987 
  1981 
  1988 	virtual bool OnKeyPress(uint16 key, uint16 keycode)
  1982 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
  1989 	{
  1983 	{
  1990 		bool cont;
  1984 		EventState state;
  1991 		switch (this->HandleEditBoxKey(4, key, keycode, cont)) {
  1985 		switch (this->HandleEditBoxKey(4, key, keycode, state)) {
  1992 			case 1: // Return
  1986 			case 1: // Return
  1993 				this->OnOk();
  1987 				this->OnOk();
  1994 				/* FALL THROUGH */
  1988 				/* FALL THROUGH */
  1995 
  1989 
  1996 			case 2: // Escape
  1990 			case 2: // Escape
  1997 				delete this;
  1991 				delete this;
  1998 				break;
  1992 				break;
  1999 		}
  1993 		}
  2000 		return cont;
  1994 		return state;
  2001 	}
  1995 	}
  2002 };
  1996 };
  2003 
  1997 
  2004 static const Widget _ncp_window_widgets[] = {
  1998 static const Widget _ncp_window_widgets[] = {
  2005 {   WWT_CLOSEBOX, RESIZE_NONE, 14,   0,  10,  0, 13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
  1999 {   WWT_CLOSEBOX, RESIZE_NONE, 14,   0,  10,  0, 13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
  2016 static const WindowDesc _ncp_window_desc = {
  2010 static const WindowDesc _ncp_window_desc = {
  2017 	WDP_AUTO, WDP_AUTO, 300, 63, 300, 63,
  2011 	WDP_AUTO, WDP_AUTO, 300, 63, 300, 63,
  2018 	WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
  2012 	WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
  2019 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
  2013 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
  2020 	_ncp_window_widgets,
  2014 	_ncp_window_widgets,
  2021 	NULL
  2015 };
  2022 };
  2016 
  2023 
  2017 void ShowNetworkCompanyPasswordWindow(Window *parent)
  2024 void ShowNetworkCompanyPasswordWindow()
       
  2025 {
  2018 {
  2026 	DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0);
  2019 	DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0);
  2027 
  2020 
  2028 	new NetworkCompanyPasswordWindow(&_ncp_window_desc);
  2021 	new NetworkCompanyPasswordWindow(&_ncp_window_desc, parent);
  2029 }
  2022 }
  2030 
  2023 
  2031 #endif /* ENABLE_NETWORK */
  2024 #endif /* ENABLE_NETWORK */