src/network/network_gui.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
   207 	item->next = NULL;
   207 	item->next = NULL;
   208 
   208 
   209 	nqld->l.flags &= ~VL_RESORT;
   209 	nqld->l.flags &= ~VL_RESORT;
   210 }
   210 }
   211 
   211 
   212 /* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
   212 /** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
       
   213 enum NetworkGameWindowWidgets {
       
   214 	NGWW_CLOSE    = 0,  ///< Close 'X' button
       
   215 	NGWW_CONN_TXT = 4,  ///< 'Connection' droplist
       
   216 	NGWW_CONN_BTN = 5,  ///< 'Connection' droplist button
       
   217 	NGWW_PLAYER   = 6,  ///< Panel with editbox to set player name
       
   218 
       
   219 	NGWW_NAME     = 7,  ///< 'Name' button
       
   220 	NGWW_CLIENTS,       ///< 'Clients' button
       
   221 	NGWW_INFO,          ///< Third button in the game list panel
       
   222 
       
   223 	NGWW_MATRIX   = 10, ///< Panel with list of games
       
   224 
       
   225 	NGWW_DETAILS  = 12, ///< Panel with game details
       
   226 	NGWW_JOIN     = 13, ///< 'Join game' button
       
   227 	NGWW_REFRESH  = 14, ///< 'Refresh server' button
       
   228 	NGWW_NEWGRF   = 15, ///< 'NewGRF Settings' button
       
   229 
       
   230 	NGWW_FIND     = 16, ///< 'Find server' button
       
   231 	NGWW_ADD,           ///< 'Add server' button
       
   232 	NGWW_START,         ///< 'Start server' button
       
   233 	NGWW_CANCEL,        ///< 'Cancel' button
       
   234 };
       
   235 
       
   236 /**
       
   237  * Handler of actions done in the NetworkStartServer window
       
   238  *
       
   239  * @param w pointer to the Window structure
       
   240  * @param e pointer to window event
       
   241  * @note    Uses network_ql_d (network_d, querystr_d and list_d) WP macro
       
   242  * @see     struct _network_game_window_widgets
       
   243  * @see     enum NetworkGameWindowWidgets
       
   244  */
       
   245 
   213 static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
   246 static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
   214 {
   247 {
   215 	network_d *nd = &WP(w, network_ql_d).n;
   248 	network_d *nd = &WP(w, network_ql_d).n;
   216 	list_d *ld = &WP(w, network_ql_d).l;
   249 	list_d *ld = &WP(w, network_ql_d).l;
   217 
   250 
   218 	switch (e->event) {
   251 	switch (e->event) {
   219 	case WE_CREATE: /* Focus input box */
   252 	case WE_CREATE: // Focus input box
   220 		w->vscroll.cap = 13;
   253 		w->vscroll.cap = 13;
   221 		w->resize.step_height = NET_PRC__SIZE_OF_ROW;
   254 		w->resize.step_height = NET_PRC__SIZE_OF_ROW;
   222 
   255 
   223 		nd->field = 3;
   256 		nd->field = NGWW_PLAYER;
   224 		nd->server = NULL;
   257 		nd->server = NULL;
   225 
   258 
   226 		WP(w, network_ql_d).sort_list = NULL;
   259 		WP(w, network_ql_d).sort_list = NULL;
   227 		ld->flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
   260 		ld->flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
   228 		ld->sort_type = _ng_sorting.criteria;
   261 		ld->sort_type = _ng_sorting.criteria;
   236 			BuildNetworkGameList(&WP(w, network_ql_d));
   269 			BuildNetworkGameList(&WP(w, network_ql_d));
   237 			SetVScrollCount(w, ld->list_length);
   270 			SetVScrollCount(w, ld->list_length);
   238 		}
   271 		}
   239 		if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
   272 		if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
   240 
   273 
   241 		SetWindowWidgetDisabledState(w, 17, sel == NULL);
   274 		/* 'Refresh' button invisible if no server selected */
   242 		/* Join Button disabling conditions */
   275 		w->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
   243 		SetWindowWidgetDisabledState(w, 16, sel == NULL || // no Selected Server
   276 		/* 'Join' button disabling conditions */
       
   277 		w->SetWidgetDisabledState(NGWW_JOIN, sel == NULL || // no Selected Server
   244 				!sel->online || // Server offline
   278 				!sel->online || // Server offline
   245 				sel->info.clients_on >= sel->info.clients_max || // Server full
   279 				sel->info.clients_on >= sel->info.clients_max || // Server full
   246 				!sel->info.compatible); // Revision mismatch
   280 				!sel->info.compatible); // Revision mismatch
   247 
   281 
   248 		SetWindowWidgetHiddenState(w, 18, sel == NULL ||
   282 		/* 'NewGRF Settings' button invisible if no NewGRF is used */
       
   283 		w->SetWidgetHiddenState(NGWW_NEWGRF, sel == NULL ||
   249 				!sel->online ||
   284 				!sel->online ||
   250 				sel->info.grfconfig == NULL);
   285 				sel->info.grfconfig == NULL);
   251 
   286 
   252 		SetDParam(0, 0x00);
   287 		SetDParam(0, 0x00);
   253 		SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
   288 		SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
   254 		DrawWindowWidgets(w);
   289 		DrawWindowWidgets(w);
   255 
   290 
   256 		DrawEditBox(w, &WP(w, network_ql_d).q, 3);
   291 		/* Edit box to set player name */
   257 
   292 		DrawEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
   258 		DrawString(9, 23, STR_NETWORK_CONNECTION, 2);
   293 
   259 		DrawString(w->widget[3].left - 100, 23, STR_NETWORK_PLAYER_NAME, 2);
   294 		DrawString(w->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
   260 
   295 
   261 		/* Sort based on widgets: name, clients, compatibility */
   296 		/* Sort based on widgets: name, clients, compatibility */
   262 		switch (ld->sort_type) {
   297 		switch (ld->sort_type) {
   263 			case 6 - 6: DoDrawString(arrow, w->widget[6].right - 10, 42, 0x10); break;
   298 			case NGWW_NAME    - NGWW_NAME: DoDrawString(arrow, w->widget[NGWW_NAME].right    - 10, 42, TC_BLACK); break;
   264 			case 7 - 6: DoDrawString(arrow, w->widget[7].right - 10, 42, 0x10); break;
   299 			case NGWW_CLIENTS - NGWW_NAME: DoDrawString(arrow, w->widget[NGWW_CLIENTS].right - 10, 42, TC_BLACK); break;
   265 			case 8 - 6: DoDrawString(arrow, w->widget[8].right - 10, 42, 0x10); break;
   300 			case NGWW_INFO    - NGWW_NAME: DoDrawString(arrow, w->widget[NGWW_INFO].right    - 10, 42, TC_BLACK); break;
   266 		}
   301 		}
   267 
   302 
   268 		{ // draw list of games
   303 		{ // draw list of games
   269 			uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
   304 			uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
   270 			int32 n = 0;
   305 			int32 n = 0;
   271 			int32 pos = w->vscroll.pos;
   306 			int32 pos = w->vscroll.pos;
   272 			uint max_name_width = w->widget[6].right - w->widget[6].left - 5;
   307 			uint max_name_width = w->widget[NGWW_NAME].right - w->widget[NGWW_NAME].left - 5;
   273 			const NetworkGameList *cur_item = _network_game_list;
   308 			const NetworkGameList *cur_item = _network_game_list;
   274 
   309 
   275 			while (pos > 0 && cur_item != NULL) {
   310 			while (pos > 0 && cur_item != NULL) {
   276 				pos--;
   311 				pos--;
   277 				cur_item = cur_item->next;
   312 				cur_item = cur_item->next;
   278 			}
   313 			}
   279 
   314 
   280 			while (cur_item != NULL) {
   315 			while (cur_item != NULL) {
   281 				// show highlighted item with a different colour
   316 				/* show highlighted item with a different colour */
   282 				if (cur_item == sel) GfxFillRect(w->widget[6].left + 1, y - 2, w->widget[8].right - 1, y + 9, 10);
   317 				if (cur_item == sel) GfxFillRect(w->widget[NGWW_NAME].left + 1, y - 2, w->widget[NGWW_INFO].right - 1, y + 9, 10);
   283 
   318 
   284 				SetDParamStr(0, cur_item->info.server_name);
   319 				SetDParamStr(0, cur_item->info.server_name);
   285 				DrawStringTruncated(w->widget[6].left + 5, y, STR_02BD, 16, max_name_width);
   320 				DrawStringTruncated(w->widget[NGWW_NAME].left + 5, y, STR_02BD, TC_BLACK, max_name_width);
   286 
   321 
   287 				SetDParam(0, cur_item->info.clients_on);
   322 				SetDParam(0, cur_item->info.clients_on);
   288 				SetDParam(1, cur_item->info.clients_max);
   323 				SetDParam(1, cur_item->info.clients_max);
   289 				SetDParam(2, cur_item->info.companies_on);
   324 				SetDParam(2, cur_item->info.companies_on);
   290 				SetDParam(3, cur_item->info.companies_max);
   325 				SetDParam(3, cur_item->info.companies_max);
   291 				DrawStringCentered(w->widget[7].left + 39, y, STR_NETWORK_GENERAL_ONLINE, 2);
   326 				DrawStringCentered(w->widget[NGWW_CLIENTS].left + 39, y, STR_NETWORK_GENERAL_ONLINE, TC_GOLD);
   292 
   327 
   293 				// only draw icons if the server is online
   328 				/* only draw icons if the server is online */
   294 				if (cur_item->online) {
   329 				if (cur_item->online) {
   295 					// draw a lock if the server is password protected.
   330 					/* draw a lock if the server is password protected */
   296 					if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, w->widget[8].left + 5, y - 1);
   331 					if (cur_item->info.use_password) DrawSprite(SPR_LOCK, PAL_NONE, w->widget[NGWW_INFO].left + 5, y - 1);
   297 
   332 
   298 					// draw red or green icon, depending on compatibility with server.
   333 					/* draw red or green icon, depending on compatibility with server */
   299 					DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[8].left + 15, y);
   334 					DrawSprite(SPR_BLOT, (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[NGWW_INFO].left + 15, y);
   300 
   335 
   301 					// draw flag according to server language
   336 					/* draw flag according to server language */
   302 					DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, w->widget[8].left + 25, y);
   337 					DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, PAL_NONE, w->widget[NGWW_INFO].left + 25, y);
   303 				}
   338 				}
   304 
   339 
   305 				cur_item = cur_item->next;
   340 				cur_item = cur_item->next;
   306 				y += NET_PRC__SIZE_OF_ROW;
   341 				y += NET_PRC__SIZE_OF_ROW;
   307 				if (++n == w->vscroll.cap) break; // max number of games in the window
   342 				if (++n == w->vscroll.cap) break; // max number of games in the window
   308 			}
   343 			}
   309 		}
   344 		}
   310 
   345 
   311 		/* Draw the right menu */
   346 		/* Draw the right menu */
   312 		GfxFillRect(w->widget[15].left + 1, 43, w->widget[15].right - 1, 92, 157);
   347 		GfxFillRect(w->widget[NGWW_DETAILS].left + 1, 43, w->widget[NGWW_DETAILS].right - 1, 92, 157);
   313 		if (sel == NULL) {
   348 		if (sel == NULL) {
   314 			DrawStringCentered(w->widget[15].left + 115, 58, STR_NETWORK_GAME_INFO, 0);
   349 			DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 58, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
   315 		} else if (!sel->online) {
   350 		} else if (!sel->online) {
   316 			SetDParamStr(0, sel->info.server_name);
   351 			SetDParamStr(0, sel->info.server_name);
   317 			DrawStringCentered(w->widget[15].left + 115, 68, STR_ORANGE, 0); // game name
   352 			DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 68, STR_ORANGE, TC_FROMSTRING); // game name
   318 
   353 
   319 			DrawStringCentered(w->widget[15].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, 0); // server offline
   354 			DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 132, STR_NETWORK_SERVER_OFFLINE, TC_FROMSTRING); // server offline
   320 		} else { // show game info
   355 		} else { // show game info
   321 			uint16 y = 100;
   356 			uint16 y = 100;
   322 			const uint16 x = w->widget[15].left + 5;
   357 			const uint16 x = w->widget[NGWW_DETAILS].left + 5;
   323 
   358 
   324 			DrawStringCentered(w->widget[15].left + 115, 48, STR_NETWORK_GAME_INFO, 0);
   359 			DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, 48, STR_NETWORK_GAME_INFO, TC_FROMSTRING);
   325 
   360 
   326 
   361 
   327 			SetDParamStr(0, sel->info.server_name);
   362 			SetDParamStr(0, sel->info.server_name);
   328 			DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 62, STR_ORANGE, 16); // game name
   363 			DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 62, STR_ORANGE, TC_BLACK); // game name
   329 
   364 
   330 			SetDParamStr(0, sel->info.map_name);
   365 			SetDParamStr(0, sel->info.map_name);
   331 			DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 74, STR_02BD, 16); // map name
   366 			DrawStringCenteredTruncated(w->widget[NGWW_DETAILS].left, w->widget[NGWW_DETAILS].right, 74, STR_02BD, TC_BLACK); // map name
   332 
   367 
   333 			SetDParam(0, sel->info.clients_on);
   368 			SetDParam(0, sel->info.clients_on);
   334 			SetDParam(1, sel->info.clients_max);
   369 			SetDParam(1, sel->info.clients_max);
   335 			SetDParam(2, sel->info.companies_on);
   370 			SetDParam(2, sel->info.companies_on);
   336 			SetDParam(3, sel->info.companies_max);
   371 			SetDParam(3, sel->info.companies_max);
   337 			DrawString(x, y, STR_NETWORK_CLIENTS, 2);
   372 			DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
   338 			y += 10;
   373 			y += 10;
   339 
   374 
   340 			SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
   375 			SetDParam(0, STR_NETWORK_LANG_ANY + sel->info.server_lang);
   341 			DrawString(x, y, STR_NETWORK_LANGUAGE, 2); // server language
   376 			DrawString(x, y, STR_NETWORK_LANGUAGE, TC_GOLD); // server language
   342 			y += 10;
   377 			y += 10;
   343 
   378 
   344 			SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
   379 			SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
   345 			DrawString(x, y, STR_NETWORK_TILESET, 2); // tileset
   380 			DrawString(x, y, STR_NETWORK_TILESET, TC_GOLD); // tileset
   346 			y += 10;
   381 			y += 10;
   347 
   382 
   348 			SetDParam(0, sel->info.map_width);
   383 			SetDParam(0, sel->info.map_width);
   349 			SetDParam(1, sel->info.map_height);
   384 			SetDParam(1, sel->info.map_height);
   350 			DrawString(x, y, STR_NETWORK_MAP_SIZE, 2); // map size
   385 			DrawString(x, y, STR_NETWORK_MAP_SIZE, TC_GOLD); // map size
   351 			y += 10;
   386 			y += 10;
   352 
   387 
   353 			SetDParamStr(0, sel->info.server_revision);
   388 			SetDParamStr(0, sel->info.server_revision);
   354 			DrawString(x, y, STR_NETWORK_SERVER_VERSION, 2); // server version
   389 			DrawString(x, y, STR_NETWORK_SERVER_VERSION, TC_GOLD); // server version
   355 			y += 10;
   390 			y += 10;
   356 
   391 
   357 			SetDParamStr(0, sel->info.hostname);
   392 			SetDParamStr(0, sel->info.hostname);
   358 			SetDParam(1, sel->port);
   393 			SetDParam(1, sel->port);
   359 			DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, 2); // server address
   394 			DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, TC_GOLD); // server address
   360 			y += 10;
   395 			y += 10;
   361 
   396 
   362 			SetDParam(0, sel->info.start_date);
   397 			SetDParam(0, sel->info.start_date);
   363 			DrawString(x, y, STR_NETWORK_START_DATE, 2); // start date
   398 			DrawString(x, y, STR_NETWORK_START_DATE, TC_GOLD); // start date
   364 			y += 10;
   399 			y += 10;
   365 
   400 
   366 			SetDParam(0, sel->info.game_date);
   401 			SetDParam(0, sel->info.game_date);
   367 			DrawString(x, y, STR_NETWORK_CURRENT_DATE, 2); // current date
   402 			DrawString(x, y, STR_NETWORK_CURRENT_DATE, TC_GOLD); // current date
   368 			y += 10;
   403 			y += 10;
   369 
   404 
   370 			y += 2;
   405 			y += 2;
   371 
   406 
   372 			if (!sel->info.compatible) {
   407 			if (!sel->info.compatible) {
   373 				DrawStringCentered(w->widget[15].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, 0); // server mismatch
   408 				DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
   374 			} else if (sel->info.clients_on == sel->info.clients_max) {
   409 			} else if (sel->info.clients_on == sel->info.clients_max) {
   375 				// Show: server full, when clients_on == clients_max
   410 				/* Show: server full, when clients_on == clients_max */
   376 				DrawStringCentered(w->widget[15].left + 115, y, STR_NETWORK_SERVER_FULL, 0); // server full
   411 				DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
   377 			} else if (sel->info.use_password) {
   412 			} else if (sel->info.use_password) {
   378 				DrawStringCentered(w->widget[15].left + 115, y, STR_NETWORK_PASSWORD, 0); // password warning
   413 				DrawStringCentered(w->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
   379 			}
   414 			}
   380 
   415 
   381 			y += 10;
   416 			y += 10;
   382 		}
   417 		}
   383 	} break;
   418 	} break;
   384 
   419 
   385 	case WE_CLICK:
   420 	case WE_CLICK:
   386 		nd->field = e->we.click.widget;
   421 		nd->field = e->we.click.widget;
   387 		switch (e->we.click.widget) {
   422 		switch (e->we.click.widget) {
   388 		case 14: // Cancel button
   423 		case NGWW_CANCEL: // Cancel button
   389 			DeleteWindowById(WC_NETWORK_WINDOW, 0);
   424 			DeleteWindowById(WC_NETWORK_WINDOW, 0);
   390 			break;
   425 			break;
   391 		case 4: case 5:
   426 		case NGWW_CONN_TXT: case NGWW_CONN_BTN: // 'Connection' droplist
   392 			ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
   427 			ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
   393 			break;
   428 			break;
   394 		case 6: /* Sort by name */
   429 		case NGWW_NAME: // Sort by name
   395 		case 7: /* Sort by connected clients */
   430 		case NGWW_CLIENTS: // Sort by connected clients
   396 		case 8: /* Connectivity (green dot) */
   431 		case NGWW_INFO: // Connectivity (green dot)
   397 			if (ld->sort_type == e->we.click.widget - 6) ld->flags ^= VL_DESC;
   432 			if (ld->sort_type == e->we.click.widget - NGWW_NAME) ld->flags ^= VL_DESC;
   398 			ld->flags |= VL_RESORT;
   433 			ld->flags |= VL_RESORT;
   399 			ld->sort_type = e->we.click.widget - 6;
   434 			ld->sort_type = e->we.click.widget - NGWW_NAME;
   400 
   435 
   401 			_ng_sorting.order = !!(ld->flags & VL_DESC);
   436 			_ng_sorting.order = !!(ld->flags & VL_DESC);
   402 			_ng_sorting.criteria = ld->sort_type;
   437 			_ng_sorting.criteria = ld->sort_type;
   403 			SetWindowDirty(w);
   438 			SetWindowDirty(w);
   404 			break;
   439 			break;
   405 		case 9: { /* Matrix to show networkgames */
   440 		case NGWW_MATRIX: { // Matrix to show networkgames
   406 			NetworkGameList *cur_item;
   441 			NetworkGameList *cur_item;
   407 			uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
   442 			uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
   408 
   443 
   409 			if (id_v >= w->vscroll.cap) return; // click out of bounds
   444 			if (id_v >= w->vscroll.cap) return; // click out of bounds
   410 			id_v += w->vscroll.pos;
   445 			id_v += w->vscroll.pos;
   413 			for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
   448 			for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
   414 
   449 
   415 			nd->server = cur_item;
   450 			nd->server = cur_item;
   416 			SetWindowDirty(w);
   451 			SetWindowDirty(w);
   417 		} break;
   452 		} break;
   418 		case 11: /* Find server automatically */
   453 		case NGWW_FIND: // Find server automatically
   419 			switch (_network_lan_internet) {
   454 			switch (_network_lan_internet) {
   420 				case 0: NetworkUDPSearchGame(); break;
   455 				case 0: NetworkUDPSearchGame(); break;
   421 				case 1: NetworkUDPQueryMasterServer(); break;
   456 				case 1: NetworkUDPQueryMasterServer(); break;
   422 			}
   457 			}
   423 			break;
   458 			break;
   424 		case 12: { // Add a server
   459 		case NGWW_ADD: { // Add a server
   425 				ShowQueryString(
   460 			ShowQueryString(
   426 				BindCString(_network_default_ip),
   461 				BindCString(_network_default_ip),
   427 				STR_NETWORK_ENTER_IP,
   462 				STR_NETWORK_ENTER_IP,
   428 				31 | 0x1000,  // maximum number of characters OR
   463 				31 | 0x1000,  // maximum number of characters OR
   429 				250, // characters up to this width pixels, whichever is satisfied first
   464 				250, // characters up to this width pixels, whichever is satisfied first
   430 				w, CS_ALPHANUMERAL);
   465 				w, CS_ALPHANUMERAL);
   431 		} break;
   466 		} break;
   432 		case 13: /* Start server */
   467 		case NGWW_START: // Start server
   433 			ShowNetworkStartServerWindow();
   468 			ShowNetworkStartServerWindow();
   434 			break;
   469 			break;
   435 		case 16: /* Join Game */
   470 		case NGWW_JOIN: // Join Game
   436 			if (nd->server != NULL) {
   471 			if (nd->server != NULL) {
   437 				snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
   472 				snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
   438 				_network_last_port = nd->server->port;
   473 				_network_last_port = nd->server->port;
   439 				ShowNetworkLobbyWindow(nd->server);
   474 				ShowNetworkLobbyWindow(nd->server);
   440 			}
   475 			}
   441 			break;
   476 			break;
   442 		case 17: // Refresh
   477 		case NGWW_REFRESH: // Refresh
   443 			if (nd->server != NULL)
   478 			if (nd->server != NULL)
   444 				NetworkUDPQueryServer(nd->server->info.hostname, nd->server->port);
   479 				NetworkUDPQueryServer(nd->server->info.hostname, nd->server->port);
   445 			break;
   480 			break;
   446 		case 18: // NewGRF Settings
   481 		case NGWW_NEWGRF: // NewGRF Settings
   447 			if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
   482 			if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
   448 			break;
   483 			break;
   449 
   484 
   450 	} break;
   485 	} break;
   451 
   486 
   452 	case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
   487 	case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
   453 		switch (e->we.dropdown.button) {
   488 		switch (e->we.dropdown.button) {
   454 			case 5:
   489 			case NGWW_CONN_BTN:
   455 				_network_lan_internet = e->we.dropdown.index;
   490 				_network_lan_internet = e->we.dropdown.index;
   456 				break;
   491 				break;
       
   492 			default:
       
   493 				NOT_REACHED();
   457 		}
   494 		}
   458 
   495 
   459 		SetWindowDirty(w);
   496 		SetWindowDirty(w);
   460 		break;
   497 		break;
   461 
   498 
   462 	case WE_MOUSELOOP:
   499 	case WE_MOUSELOOP:
   463 		if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
   500 		if (nd->field == NGWW_PLAYER) HandleEditBox(w, &WP(w, network_ql_d).q, NGWW_PLAYER);
   464 		break;
   501 		break;
   465 
   502 
   466 	case WE_MESSAGE:
   503 	case WE_MESSAGE:
   467 		if (e->we.message.msg != 0) nd->server = NULL;
   504 		if (e->we.message.msg != 0) nd->server = NULL;
   468 		ld->flags |= VL_REBUILD;
   505 		ld->flags |= VL_REBUILD;
   469 		SetWindowDirty(w);
   506 		SetWindowDirty(w);
   470 		break;
   507 		break;
   471 
   508 
   472 	case WE_KEYPRESS:
   509 	case WE_KEYPRESS:
   473 		if (nd->field != 3) {
   510 		if (nd->field != NGWW_PLAYER) {
   474 			if (nd->server != NULL) {
   511 			if (nd->server != NULL) {
   475 				if (e->we.keypress.keycode == WKC_DELETE) { /* Press 'delete' to remove servers */
   512 				if (e->we.keypress.keycode == WKC_DELETE) { // Press 'delete' to remove servers
   476 					NetworkGameListRemoveItem(nd->server);
   513 					NetworkGameListRemoveItem(nd->server);
   477 					NetworkRebuildHostList();
   514 					NetworkRebuildHostList();
   478 					nd->server = NULL;
   515 					nd->server = NULL;
   479 				}
   516 				}
   480 			}
   517 			}
   481 			break;
   518 			break;
   482 		}
   519 		}
   483 
   520 
   484 		if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
   521 		if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NGWW_PLAYER, e) == 1) break; // enter pressed
   485 
   522 
   486 		// The name is only allowed when it starts with a letter!
   523 		/* The name is only allowed when it starts with a letter! */
   487 		if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
   524 		if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
   488 			ttd_strlcpy(_network_player_name, _edit_str_buf, lengthof(_network_player_name));
   525 			ttd_strlcpy(_network_player_name, _edit_str_buf, lengthof(_network_player_name));
   489 		} else {
   526 		} else {
   490 			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
   527 			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
   491 		}
   528 		}
   498 		break;
   535 		break;
   499 
   536 
   500 	case WE_RESIZE: {
   537 	case WE_RESIZE: {
   501 		w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
   538 		w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
   502 
   539 
   503 		w->widget[9].data = (w->vscroll.cap << 8) + 1;
   540 		w->widget[NGWW_MATRIX].data = (w->vscroll.cap << 8) + 1;
   504 
   541 
   505 		int widget_width = w->widget[11].right - w->widget[11].left;
   542 		SetVScrollCount(w, ld->list_length);
       
   543 
       
   544 		int widget_width = w->widget[NGWW_FIND].right - w->widget[NGWW_FIND].left;
   506 		int space = (w->width - 4 * widget_width - 25) / 3;
   545 		int space = (w->width - 4 * widget_width - 25) / 3;
   507 
   546 
   508 		int offset = 10;
   547 		int offset = 10;
   509 		for (uint i = 0; i < 4; i++) {
   548 		for (uint i = 0; i < 4; i++) {
   510 			w->widget[11 + i].left  = offset;
   549 			w->widget[NGWW_FIND + i].left  = offset;
   511 			offset += widget_width;
   550 			offset += widget_width;
   512 			w->widget[11 + i].right = offset;
   551 			w->widget[NGWW_FIND + i].right = offset;
   513 			offset += space;
   552 			offset += space;
   514 		}
   553 		}
   515 	} break;
   554 	} break;
   516 
   555 
   517 	case WE_DESTROY: /* Nicely clean up the sort-list */
   556 	case WE_DESTROY: // Nicely clean up the sort-list
   518 		free(WP(w, network_ql_d).sort_list);
   557 		free(WP(w, network_ql_d).sort_list);
   519 		break;
   558 		break;
   520 	}
   559 	}
   521 }
   560 }
   522 
   561 
   523 static const Widget _network_game_window_widgets[] = {
   562 static const Widget _network_game_window_widgets[] = {
   524 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},
   563 /* TOP */
       
   564 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW},            // NGWW_CLOSE
   525 {    WWT_CAPTION,   RESIZE_RIGHT,  BGC,    11,   449,     0,    13, STR_NETWORK_MULTIPLAYER,        STR_NULL},
   565 {    WWT_CAPTION,   RESIZE_RIGHT,  BGC,    11,   449,     0,    13, STR_NETWORK_MULTIPLAYER,        STR_NULL},
   526 {      WWT_PANEL,   RESIZE_RB,     BGC,     0,   449,    14,   263, 0x0,                            STR_NULL},
   566 {      WWT_PANEL,   RESIZE_RB,     BGC,     0,   449,    14,   263, 0x0,                            STR_NULL},
   527 
   567 
       
   568 {       WWT_TEXT,   RESIZE_NONE,   BGC,     9,    85,    23,    35, STR_NETWORK_CONNECTION,         STR_NULL},
       
   569 {      WWT_INSET,   RESIZE_NONE,   BGC,    90,   181,    22,    33, STR_NETWORK_LAN_INTERNET_COMBO, STR_NETWORK_CONNECTION_TIP},       // NGWW_CONN_TXT
       
   570 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   170,   180,    23,    32, STR_0225,                       STR_NETWORK_CONNECTION_TIP},       // NGWW_CONN_BTN
       
   571 
       
   572 {      WWT_PANEL,   RESIZE_LR,     BGC,   290,   440,    22,    33, 0x0,                            STR_NETWORK_ENTER_NAME_TIP},       // NGWW_PLAYER
       
   573 
   528 /* LEFT SIDE */
   574 /* LEFT SIDE */
   529 {      WWT_PANEL,   RESIZE_LR,     BGC,   290,   440,    22,    33, 0x0,                            STR_NETWORK_ENTER_NAME_TIP},
   575 { WWT_PUSHTXTBTN,   RESIZE_RIGHT,  BTC,    10,    70,    42,    53, STR_NETWORK_GAME_NAME,          STR_NETWORK_GAME_NAME_TIP},        // NGWW_NAME
   530 
   576 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,    71,   150,    42,    53, STR_NETWORK_CLIENTS_CAPTION,    STR_NETWORK_CLIENTS_CAPTION_TIP},  // NGWW_CLIENTS
   531 {      WWT_INSET,   RESIZE_NONE,   BGC,    90,   181,    22,    33, STR_NETWORK_LAN_INTERNET_COMBO, STR_NETWORK_CONNECTION_TIP},
   577 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,   151,   190,    42,    53, STR_EMPTY,                      STR_NETWORK_INFO_ICONS_TIP},       // NGWW_INFO
   532 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   170,   180,    23,    32, STR_0225,                       STR_NETWORK_CONNECTION_TIP},
   578 
   533 
   579 {     WWT_MATRIX,   RESIZE_RB,     BGC,    10,   190,    54,   236, (13 << 8) + 1,                  STR_NETWORK_CLICK_GAME_TO_SELECT}, // NGWW_MATRIX
   534 { WWT_PUSHTXTBTN,   RESIZE_RIGHT,  BTC,    10,    70,    42,    53, STR_NETWORK_GAME_NAME,          STR_NETWORK_GAME_NAME_TIP},
   580 {  WWT_SCROLLBAR,   RESIZE_LRB,    BGC,   191,   202,    42,   236, 0x0,                            STR_0190_SCROLL_BAR_SCROLLS_LIST},
   535 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,    71,   150,    42,    53, STR_NETWORK_CLIENTS_CAPTION,    STR_NETWORK_CLIENTS_CAPTION_TIP},
       
   536 { WWT_PUSHTXTBTN,   RESIZE_LR,     BTC,   151,   190,    42,    53, STR_EMPTY,                      STR_NETWORK_INFO_ICONS_TIP},
       
   537 
       
   538 {     WWT_MATRIX,   RESIZE_RB,     BGC,    10,   190,    54,   236, (13 << 8) + 1,                  STR_NETWORK_CLICK_GAME_TO_SELECT},
       
   539 {  WWT_SCROLLBAR,   RESIZE_LRB,    BGC,   191,   202,    42,   236, STR_NULL,                       STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
   540 
       
   541 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,    10,   110,   246,   257, STR_NETWORK_FIND_SERVER,        STR_NETWORK_FIND_SERVER_TIP},
       
   542 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   118,   218,   246,   257, STR_NETWORK_ADD_SERVER,         STR_NETWORK_ADD_SERVER_TIP},
       
   543 
   581 
   544 /* RIGHT SIDE */
   582 /* RIGHT SIDE */
   545 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   226,   326,   246,   257, STR_NETWORK_START_SERVER,       STR_NETWORK_START_SERVER_TIP},
   583 {      WWT_PANEL,   RESIZE_LRB,    BGC,   210,   440,    42,   236, 0x0,                            STR_NULL},                         // NGWW_DETAILS
   546 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   334,   434,   246,   257, STR_012E_CANCEL,                STR_NULL},
   584 
   547 
   585 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   215,   315,   215,   226, STR_NETWORK_JOIN_GAME,          STR_NULL},                         // NGWW_JOIN
   548 {      WWT_PANEL,   RESIZE_LRB,    BGC,   210,   440,    42,   236, 0x0,                            STR_NULL},
   586 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   330,   435,   215,   226, STR_NETWORK_REFRESH,            STR_NETWORK_REFRESH_TIP},          // NGWW_REFRESH
   549 
   587 
   550 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   215,   315,   215,   226, STR_NETWORK_JOIN_GAME,          STR_NULL},
   588 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   330,   435,   197,   208, STR_NEWGRF_SETTINGS_BUTTON,     STR_NULL},                         // NGWW_NEWGRF
   551 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   330,   435,   215,   226, STR_NETWORK_REFRESH,            STR_NETWORK_REFRESH_TIP},
   589 
   552 
   590 /* BOTTOM */
   553 { WWT_PUSHTXTBTN,   RESIZE_LRTB,   BTC,   330,   435,   197,   208, STR_NEWGRF_SETTINGS_BUTTON,     STR_NULL},
   591 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,    10,   110,   246,   257, STR_NETWORK_FIND_SERVER,        STR_NETWORK_FIND_SERVER_TIP},      // NGWW_FIND
       
   592 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   118,   218,   246,   257, STR_NETWORK_ADD_SERVER,         STR_NETWORK_ADD_SERVER_TIP},       // NGWW_ADD
       
   593 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   226,   326,   246,   257, STR_NETWORK_START_SERVER,       STR_NETWORK_START_SERVER_TIP},     // NGWW_START
       
   594 { WWT_PUSHTXTBTN,   RESIZE_TB,     BTC,   334,   434,   246,   257, STR_012E_CANCEL,                STR_NULL},                         // NGWW_CANCEL
   554 
   595 
   555 {  WWT_RESIZEBOX,   RESIZE_LRTB,   BGC,   438,   449,   252,   263, 0x0,                            STR_RESIZE_BUTTON },
   596 {  WWT_RESIZEBOX,   RESIZE_LRTB,   BGC,   438,   449,   252,   263, 0x0,                            STR_RESIZE_BUTTON },
   556 
   597 
   557 {   WIDGETS_END},
   598 {   WIDGETS_END},
   558 };
   599 };
   600 enum {
   641 enum {
   601 	NSSWND_START = 64,
   642 	NSSWND_START = 64,
   602 	NSSWND_ROWSIZE = 12
   643 	NSSWND_ROWSIZE = 12
   603 };
   644 };
   604 
   645 
   605 /* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
   646 /** Enum for NetworkStartServerWindow, referring to _network_start_server_window_widgets */
       
   647 enum NetworkStartServerWidgets {
       
   648 	NSSW_CLOSE           =  0,   ///< Close 'X' button
       
   649 	NSSW_GAMENAME        =  4,   ///< Background for editbox to set game name
       
   650 	NSSW_SETPWD          =  5,   ///< 'Set password' button
       
   651 	NSSW_SELMAP          =  7,   ///< 'Select map' list
       
   652 	NSSW_CONNTYPE_TXT    = 10,   ///< 'Connection type' droplist
       
   653 	NSSW_CONNTYPE_BTN    = 11,   ///< 'Connection type' droplist button
       
   654 	NSSW_CLIENTS_BTND    = 13,   ///< 'Max clients' downarrow
       
   655 	NSSW_CLIENTS_TXT     = 14,   ///< 'Max clients' text
       
   656 	NSSW_CLIENTS_BTNU    = 15,   ///< 'Max clients' uparrow
       
   657 	NSSW_COMPANIES_BTND  = 17,   ///< 'Max companies' downarrow
       
   658 	NSSW_COMPANIES_TXT   = 18,   ///< 'Max companies' text
       
   659 	NSSW_COMPANIES_BTNU  = 19,   ///< 'Max companies' uparrow
       
   660 	NSSW_SPECTATORS_BTND = 21,   ///< 'Max spectators' downarrow
       
   661 	NSSW_SPECTATORS_TXT  = 22,   ///< 'Max spectators' text
       
   662 	NSSW_SPECTATORS_BTNU = 23,   ///< 'Max spectators' uparrow
       
   663 	NSSW_LANGUAGE_TXT    = 25,   ///< 'Language spoken' droplist
       
   664 	NSSW_LANGUAGE_BTN    = 26,   ///< 'Language spoken' droplist button
       
   665 	NSSW_START           = 27,   ///< 'Start' button
       
   666 	NSSW_LOAD            = 28,   ///< 'Load' button
       
   667 	NSSW_CANCEL          = 29,   ///< 'Cancel' button
       
   668 };
       
   669 
       
   670 /**
       
   671  * Handler of actions done in the NetworkStartServer window
       
   672  *
       
   673  * @param w pointer to the Window structure
       
   674  * @param e pointer to window event
       
   675  * @note    Uses network_ql_d (network_d, querystr_d and list_d) WP macro
       
   676  * @see     struct _network_start_server_window_widgets
       
   677  * @see     enum NetworkStartServerWidgets
       
   678  */
   606 static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
   679 static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
   607 {
   680 {
   608 	network_d *nd = &WP(w, network_ql_d).n;
   681 	network_d *nd = &WP(w, network_ql_d).n;
   609 
   682 
   610 	switch (e->event) {
   683 	switch (e->event) {
   611 	case WE_CREATE: /* focus input box */
   684 	case WE_CREATE: // focus input box
   612 		nd->field = 3;
   685 		nd->field = NSSW_GAMENAME;
   613 		_network_game_info.use_password = (_network_server_password[0] != '\0');
   686 		_network_game_info.use_password = (_network_server_password[0] != '\0');
   614 		break;
   687 		break;
   615 
   688 
   616 	case WE_PAINT: {
   689 	case WE_PAINT: {
   617 		int y = NSSWND_START, pos;
   690 		int y = NSSWND_START, pos;
   618 		const FiosItem *item;
   691 		const FiosItem *item;
   619 
   692 
       
   693 		/* draw basic widgets */
   620 		SetDParam(1, _connection_types_dropdown[_network_advertise]);
   694 		SetDParam(1, _connection_types_dropdown[_network_advertise]);
   621 		SetDParam(2, _network_game_info.clients_max);
   695 		SetDParam(2, _network_game_info.clients_max);
   622 		SetDParam(3, _network_game_info.companies_max);
   696 		SetDParam(3, _network_game_info.companies_max);
   623 		SetDParam(4, _network_game_info.spectators_max);
   697 		SetDParam(4, _network_game_info.spectators_max);
   624 		SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
   698 		SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
   625 		DrawWindowWidgets(w);
   699 		DrawWindowWidgets(w);
   626 
   700 
   627 		GfxFillRect(11, 63, 258, 215, 0xD7);
   701 		/* editbox to set game name */
   628 		DrawEditBox(w, &WP(w, network_ql_d).q, 3);
   702 		DrawEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
   629 
   703 
   630 		DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2);
   704 		/* if password is set, draw red '*' next to 'Set password' button */
   631 
   705 		if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
   632 		DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2);
   706 
   633 
   707 		/* draw list of maps */
   634 		DrawString(280,  63, STR_NETWORK_CONNECTION, 2);
   708 		GfxFillRect(11, 63, 258, 215, 0xD7);  // black background of maps list
   635 		DrawString(280,  95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
   709 
   636 		DrawString(280, 127, STR_NETWORK_NUMBER_OF_COMPANIES, 2);
       
   637 		DrawString(280, 159, STR_NETWORK_NUMBER_OF_SPECTATORS, 2);
       
   638 		DrawString(280, 191, STR_NETWORK_LANGUAGE_SPOKEN, 2);
       
   639 
       
   640 		if (_network_game_info.use_password) DoDrawString("*", 408, 23, 3);
       
   641 
       
   642 		// draw list of maps
       
   643 		pos = w->vscroll.pos;
   710 		pos = w->vscroll.pos;
   644 		while (pos < _fios_num + 1) {
   711 		while (pos < _fios_num + 1) {
   645 			item = _fios_list + pos - 1;
   712 			item = _fios_list + pos - 1;
   646 			if (item == nd->map || (pos == 0 && nd->map == NULL))
   713 			if (item == nd->map || (pos == 0 && nd->map == NULL))
   647 				GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
   714 				GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
   648 
   715 
   649 			if (pos == 0) {
   716 			if (pos == 0) {
   650 				DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
   717 				DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, TC_DARK_GREEN);
   651 			} else {
   718 			} else {
   652 				DoDrawString(item->title, 14, y, _fios_colors[item->type] );
   719 				DoDrawString(item->title, 14, y, _fios_colors[item->type] );
   653 			}
   720 			}
   654 			pos++;
   721 			pos++;
   655 			y += NSSWND_ROWSIZE;
   722 			y += NSSWND_ROWSIZE;
   659 	} break;
   726 	} break;
   660 
   727 
   661 	case WE_CLICK:
   728 	case WE_CLICK:
   662 		nd->field = e->we.click.widget;
   729 		nd->field = e->we.click.widget;
   663 		switch (e->we.click.widget) {
   730 		switch (e->we.click.widget) {
   664 		case 0: /* Close 'X' */
   731 		case NSSW_CLOSE:  // Close 'X'
   665 		case 22: /* Cancel button */
   732 		case NSSW_CANCEL: // Cancel button
   666 			ShowNetworkGameWindow();
   733 			ShowNetworkGameWindow();
   667 			break;
   734 			break;
   668 
   735 
   669 		case 4: /* Set password button */
   736 		case NSSW_SETPWD: // Set password button
   670 			nd->widget_id = 4;
   737 			nd->widget_id = NSSW_SETPWD;
   671 			ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
   738 			ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
   672 			break;
   739 			break;
   673 
   740 
   674 		case 5: { /* Select map */
   741 		case NSSW_SELMAP: { // Select map
   675 			int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
   742 			int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
   676 
   743 
   677 			y += w->vscroll.pos;
   744 			y += w->vscroll.pos;
   678 			if (y >= w->vscroll.count) return;
   745 			if (y >= w->vscroll.count) return;
   679 
   746 
   680 			nd->map = (y == 0) ? NULL : _fios_list + y - 1;
   747 			nd->map = (y == 0) ? NULL : _fios_list + y - 1;
   681 			SetWindowDirty(w);
   748 			SetWindowDirty(w);
   682 			} break;
   749 			} break;
   683 		case 7: case 8: /* Connection type */
   750 		case NSSW_CONNTYPE_TXT: case NSSW_CONNTYPE_BTN: // Connection type
   684 			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
   751 			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, NSSW_CONNTYPE_BTN, 0, 0); // do it for widget NSSW_CONNTYPE_BTN
   685 			break;
   752 			break;
   686 		case  9: case 11: // Click on up/down button for number of players
   753 		case NSSW_CLIENTS_BTND:    case NSSW_CLIENTS_BTNU:    // Click on up/down button for number of clients
   687 		case 12: case 14: // Click on up/down button for number of companies
   754 		case NSSW_COMPANIES_BTND:  case NSSW_COMPANIES_BTNU:  // Click on up/down button for number of companies
   688 		case 15: case 17: // Click on up/down button for number of spectators
   755 		case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU: // Click on up/down button for number of spectators
   689 			/* Don't allow too fast scrolling */
   756 			/* Don't allow too fast scrolling */
   690 			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
   757 			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
   691 				HandleButtonClick(w, e->we.click.widget);
   758 				HandleButtonClick(w, e->we.click.widget);
   692 				SetWindowDirty(w);
   759 				SetWindowDirty(w);
   693 				switch (e->we.click.widget) {
   760 				switch (e->we.click.widget) {
   694 					default: NOT_REACHED();
   761 					default: NOT_REACHED();
   695 					case  9: case 11: _network_game_info.clients_max    = clamp(_network_game_info.clients_max    + e->we.click.widget - 10, 2, MAX_CLIENTS); break;
   762 					case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
   696 					case 12: case 14: _network_game_info.companies_max  = clamp(_network_game_info.companies_max  + e->we.click.widget - 13, 1, MAX_PLAYERS); break;
   763 						_network_game_info.clients_max    = Clamp(_network_game_info.clients_max    + e->we.click.widget - NSSW_CLIENTS_TXT,    2, MAX_CLIENTS);
   697 					case 15: case 17: _network_game_info.spectators_max = clamp(_network_game_info.spectators_max + e->we.click.widget - 16, 0, MAX_CLIENTS); break;
   764 						break;
       
   765 					case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
       
   766 						_network_game_info.companies_max  = Clamp(_network_game_info.companies_max  + e->we.click.widget - NSSW_COMPANIES_TXT,  1, MAX_PLAYERS);
       
   767 						break;
       
   768 					case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
       
   769 						_network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + e->we.click.widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
       
   770 						break;
   698 				}
   771 				}
   699 			}
   772 			}
   700 			_left_button_clicked = false;
   773 			_left_button_clicked = false;
   701 			break;
   774 			break;
   702 		case 10: // Click on number of players
   775 		case NSSW_CLIENTS_TXT:    // Click on number of players
   703 			nd->widget_id = 10;
   776 			nd->widget_id = NSSW_CLIENTS_TXT;
   704 			SetDParam(0, _network_game_info.clients_max);
   777 			SetDParam(0, _network_game_info.clients_max);
   705 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, w, CS_NUMERAL);
   778 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS,    3, 50, w, CS_NUMERAL);
   706 			break;
   779 			break;
   707 		case 13: // Click on number of companies
   780 		case NSSW_COMPANIES_TXT:  // Click on number of companies
   708 			nd->widget_id = 13;
   781 			nd->widget_id = NSSW_COMPANIES_TXT;
   709 			SetDParam(0, _network_game_info.companies_max);
   782 			SetDParam(0, _network_game_info.companies_max);
   710 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, w, CS_NUMERAL);
   783 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES,  3, 50, w, CS_NUMERAL);
   711 			break;
   784 			break;
   712 		case 16: // Click on number of companies
   785 		case NSSW_SPECTATORS_TXT: // Click on number of spectators
   713 			nd->widget_id = 16;
   786 			nd->widget_id = NSSW_SPECTATORS_TXT;
   714 			SetDParam(0, _network_game_info.spectators_max);
   787 			SetDParam(0, _network_game_info.spectators_max);
   715 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, w, CS_NUMERAL);
   788 			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, w, CS_NUMERAL);
   716 			break;
   789 			break;
   717 		case 18: case 19: { /* Language */
   790 		case NSSW_LANGUAGE_TXT: case NSSW_LANGUAGE_BTN: { // Language
   718 			uint sel = 0;
   791 			uint sel = 0;
   719 			for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
   792 			for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
   720 				if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
   793 				if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
   721 					sel = i;
   794 					sel = i;
   722 					break;
   795 					break;
   723 				}
   796 				}
   724 			}
   797 			}
   725 			ShowDropDownMenu(w, _language_dropdown, sel, 19, 0, 0);
   798 			ShowDropDownMenu(w, _language_dropdown, sel, NSSW_LANGUAGE_BTN, 0, 0);
   726 			break;
   799 			break;
   727 		}
   800 		}
   728 		case 20: /* Start game */
   801 		case NSSW_START: // Start game
   729 			_is_network_server = true;
   802 			_is_network_server = true;
   730 
   803 
   731 			if (nd->map == NULL) { // start random new game
   804 			if (nd->map == NULL) { // start random new game
   732 				ShowGenerateLandscape();
   805 				ShowGenerateLandscape();
   733 			} else { // load a scenario
   806 			} else { // load a scenario
   740 					DeleteWindow(w);
   813 					DeleteWindow(w);
   741 					SwitchMode(SM_START_SCENARIO);
   814 					SwitchMode(SM_START_SCENARIO);
   742 				}
   815 				}
   743 			}
   816 			}
   744 			break;
   817 			break;
   745 		case 21: /* Load game */
   818 		case NSSW_LOAD: // Load game
   746 			_is_network_server = true;
   819 			_is_network_server = true;
   747 			/* XXX - WC_NETWORK_WINDOW should stay, but if it stays, it gets
   820 			/* XXX - WC_NETWORK_WINDOW (this window) should stay, but if it stays, it gets
   748 			 * copied all the elements of 'load game' and upon closing that, it segfaults */
   821 			 * copied all the elements of 'load game' and upon closing that, it segfaults */
   749 			DeleteWindowById(WC_NETWORK_WINDOW, 0);
   822 			DeleteWindow(w);
   750 			ShowSaveLoadDialog(SLD_LOAD_GAME);
   823 			ShowSaveLoadDialog(SLD_LOAD_GAME);
   751 			break;
   824 			break;
   752 		}
   825 		}
   753 		break;
   826 		break;
   754 
   827 
   755 	case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
   828 	case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
   756 		switch (e->we.dropdown.button) {
   829 		switch (e->we.dropdown.button) {
   757 			case  8: _network_advertise                = (e->we.dropdown.index != 0); break;
   830 			case NSSW_CONNTYPE_BTN:
   758 			case 10: _network_game_info.clients_max    = e->we.dropdown.index;        break;
   831 				_network_advertise = (e->we.dropdown.index != 0);
   759 			case 12: _network_game_info.companies_max  = e->we.dropdown.index;        break;
   832 				break;
   760 			case 14: _network_game_info.spectators_max = e->we.dropdown.index;        break;
   833 			case NSSW_LANGUAGE_BTN:
   761 			case 16:
       
   762 				_network_game_info.server_lang = _language_dropdown[e->we.dropdown.index] - STR_NETWORK_LANG_ANY;
   834 				_network_game_info.server_lang = _language_dropdown[e->we.dropdown.index] - STR_NETWORK_LANG_ANY;
   763 				break;
   835 				break;
       
   836 			default:
       
   837 				NOT_REACHED();
   764 		}
   838 		}
   765 
   839 
   766 		SetWindowDirty(w);
   840 		SetWindowDirty(w);
   767 		break;
   841 		break;
   768 
   842 
   769 	case WE_MOUSELOOP:
   843 	case WE_MOUSELOOP:
   770 		if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
   844 		if (nd->field == NSSW_GAMENAME) HandleEditBox(w, &WP(w, network_ql_d).q, NSSW_GAMENAME);
   771 		break;
   845 		break;
   772 
   846 
   773 	case WE_KEYPRESS:
   847 	case WE_KEYPRESS:
   774 		if (nd->field == 3) {
   848 		if (nd->field == NSSW_GAMENAME) {
   775 			if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
   849 			if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, NSSW_GAMENAME, e) == 1) break; // enter pressed
   776 
   850 
   777 			ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
   851 			ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
   778 		}
   852 		}
   779 		break;
   853 		break;
   780 
   854 
   781 	case WE_ON_EDIT_TEXT:
   855 	case WE_ON_EDIT_TEXT:
   782 		if (e->we.edittext.str == NULL) break;
   856 		if (e->we.edittext.str == NULL) break;
   783 
   857 
   784 		if (nd->widget_id == 4) {
   858 		if (nd->widget_id == NSSW_SETPWD) {
   785 			ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
   859 			ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
   786 			_network_game_info.use_password = (_network_server_password[0] != '\0');
   860 			_network_game_info.use_password = (_network_server_password[0] != '\0');
   787 		} else {
   861 		} else {
   788 			int32 value = atoi(e->we.edittext.str);
   862 			int32 value = atoi(e->we.edittext.str);
   789 			InvalidateWidget(w, nd->widget_id);
   863 			InvalidateWidget(w, nd->widget_id);
   790 			switch (nd->widget_id) {
   864 			switch (nd->widget_id) {
   791 				default: NOT_REACHED();
   865 				default: NOT_REACHED();
   792 				case 10: _network_game_info.clients_max    = clamp(value, 2, MAX_CLIENTS); break;
   866 				case NSSW_CLIENTS_TXT:    _network_game_info.clients_max    = Clamp(value, 2, MAX_CLIENTS); break;
   793 				case 13: _network_game_info.companies_max  = clamp(value, 1, MAX_PLAYERS); break;
   867 				case NSSW_COMPANIES_TXT:  _network_game_info.companies_max  = Clamp(value, 1, MAX_PLAYERS); break;
   794 				case 16: _network_game_info.spectators_max = clamp(value, 0, MAX_CLIENTS); break;
   868 				case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
   795 			}
   869 			}
   796 		}
   870 		}
   797 
   871 
   798 		SetWindowDirty(w);
   872 		SetWindowDirty(w);
   799 		break;
   873 		break;
   800 	}
   874 	}
   801 }
   875 }
   802 
   876 
   803 static const Widget _network_start_server_window_widgets[] = {
   877 static const Widget _network_start_server_window_widgets[] = {
   804 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW },
   878 /* Window decoration and background panel */
   805 {    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_START_GAME_WINDOW,  STR_NULL},
   879 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW },               // NSSW_CLOSE
   806 {      WWT_PANEL,   RESIZE_NONE,   BGC,     0,   419,    14,   243, 0x0,                            STR_NULL},
   880 {    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_START_GAME_WINDOW,    STR_NULL},
   807 
   881 {      WWT_PANEL,   RESIZE_NONE,   BGC,     0,   419,    14,   243, 0x0,                              STR_NULL},
   808 {      WWT_PANEL,   RESIZE_NONE,   BGC,   100,   272,    22,    33, 0x0,                            STR_NETWORK_NEW_GAME_NAME_TIP},
   882 
   809 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   285,   405,    22,    33, STR_NETWORK_SET_PASSWORD,       STR_NETWORK_PASSWORD_TIP},
   883 /* Set game name and password widgets */
   810 
   884 {       WWT_TEXT,   RESIZE_NONE,   BGC,    10,    90,    22,    34, STR_NETWORK_NEW_GAME_NAME,        STR_NULL},
   811 {      WWT_INSET,   RESIZE_NONE,   BGC,    10,   271,    62,   216, 0x0,                            STR_NETWORK_SELECT_MAP_TIP},
   885 {      WWT_PANEL,   RESIZE_NONE,   BGC,   100,   272,    22,    33, 0x0,                              STR_NETWORK_NEW_GAME_NAME_TIP},        // NSSW_GAMENAME
   812 {  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   259,   270,    63,   215, 0x0,                            STR_0190_SCROLL_BAR_SCROLLS_LIST},
   886 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   285,   405,    22,    33, STR_NETWORK_SET_PASSWORD,         STR_NETWORK_PASSWORD_TIP},             // NSSW_SETPWD
       
   887 
       
   888 /* List of playable scenarios */
       
   889 {       WWT_TEXT,   RESIZE_NONE,   BGC,    10,   110,    43,    55, STR_NETWORK_SELECT_MAP,           STR_NULL},
       
   890 {      WWT_INSET,   RESIZE_NONE,   BGC,    10,   271,    62,   216, STR_NULL,                         STR_NETWORK_SELECT_MAP_TIP},           // NSSW_SELMAP
       
   891 {  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   259,   270,    63,   215, 0x0,                              STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
   892 
   813 /* Combo/selection boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
   893 /* Combo/selection boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
   814 {      WWT_INSET,   RESIZE_NONE,   BGC,   280,   410,    77,    88, STR_NETWORK_LAN_INTERNET_COMBO, STR_NETWORK_CONNECTION_TIP},
   894 {       WWT_TEXT,   RESIZE_NONE,   BGC,   280,   419,    63,    75, STR_NETWORK_CONNECTION,           STR_NULL},
   815 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,    78,    87, STR_0225,                       STR_NETWORK_CONNECTION_TIP},
   895 {      WWT_INSET,   RESIZE_NONE,   BGC,   280,   410,    77,    88, STR_NETWORK_LAN_INTERNET_COMBO,   STR_NETWORK_CONNECTION_TIP},           // NSSW_CONNTYPE_TXT
   816 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   109,   120, SPR_ARROW_DOWN,                 STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
   896 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,    78,    87, STR_0225,                         STR_NETWORK_CONNECTION_TIP},           // NSSW_CONNTYPE_BTN
   817 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   109,   120, STR_NETWORK_CLIENTS_SELECT,     STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
   897 
   818 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   109,   120, SPR_ARROW_UP,                   STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
   898 {       WWT_TEXT,   RESIZE_NONE,   BGC,   280,   419,    95,   107, STR_NETWORK_NUMBER_OF_CLIENTS,    STR_NULL},
   819 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   141,   152, SPR_ARROW_DOWN,                 STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
   899 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   109,   120, SPR_ARROW_DOWN,                   STR_NETWORK_NUMBER_OF_CLIENTS_TIP},    // NSSW_CLIENTS_BTND
   820 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   141,   152, STR_NETWORK_COMPANIES_SELECT,   STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
   900 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   109,   120, STR_NETWORK_CLIENTS_SELECT,       STR_NETWORK_NUMBER_OF_CLIENTS_TIP},    // NSSW_CLIENTS_TXT
   821 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   141,   152, SPR_ARROW_UP,                   STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
   901 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   109,   120, SPR_ARROW_UP,                     STR_NETWORK_NUMBER_OF_CLIENTS_TIP},    // NSSW_CLIENTS_BTNU
   822 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   173,   184, SPR_ARROW_DOWN,                 STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
   902 
   823 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   173,   184, STR_NETWORK_SPECTATORS_SELECT,  STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
   903 {       WWT_TEXT,   RESIZE_NONE,   BGC,   280,   419,   127,   139, STR_NETWORK_NUMBER_OF_COMPANIES,  STR_NULL},
   824 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   173,   184, SPR_ARROW_UP,                   STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
   904 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   141,   152, SPR_ARROW_DOWN,                   STR_NETWORK_NUMBER_OF_COMPANIES_TIP},  // NSSW_COMPANIES_BTND
   825 
   905 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   141,   152, STR_NETWORK_COMPANIES_SELECT,     STR_NETWORK_NUMBER_OF_COMPANIES_TIP},  // NSSW_COMPANIES_TXT
   826 {      WWT_INSET,   RESIZE_NONE,   BGC,   280,   410,   205,   216, STR_NETWORK_LANGUAGE_COMBO,     STR_NETWORK_LANGUAGE_TIP},
   906 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   141,   152, SPR_ARROW_UP,                     STR_NETWORK_NUMBER_OF_COMPANIES_TIP},  // NSSW_COMPANIES_BTNU
   827 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   206,   215, STR_0225,                       STR_NETWORK_LANGUAGE_TIP},
   907 
   828 
   908 {       WWT_TEXT,   RESIZE_NONE,   BGC,   280,   419,   159,   171, STR_NETWORK_NUMBER_OF_SPECTATORS, STR_NULL},
   829 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    40,   140,   224,   235, STR_NETWORK_START_GAME,         STR_NETWORK_START_GAME_TIP},
   909 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   173,   184, SPR_ARROW_DOWN,                   STR_NETWORK_NUMBER_OF_SPECTATORS_TIP}, // NSSW_SPECTATORS_BTND
   830 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   150,   250,   224,   235, STR_NETWORK_LOAD_GAME,          STR_NETWORK_LOAD_GAME_TIP},
   910 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   173,   184, STR_NETWORK_SPECTATORS_SELECT,    STR_NETWORK_NUMBER_OF_SPECTATORS_TIP}, // NSSW_SPECTATORS_TXT
   831 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   260,   360,   224,   235, STR_012E_CANCEL,                STR_NULL},
   911 {     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   173,   184, SPR_ARROW_UP,                     STR_NETWORK_NUMBER_OF_SPECTATORS_TIP}, // NSSW_SPECTATORS_BTNU
       
   912 
       
   913 {       WWT_TEXT,   RESIZE_NONE,   BGC,   280,   419,   191,   203, STR_NETWORK_LANGUAGE_SPOKEN,      STR_NULL},
       
   914 {      WWT_INSET,   RESIZE_NONE,   BGC,   280,   410,   205,   216, STR_NETWORK_LANGUAGE_COMBO,       STR_NETWORK_LANGUAGE_TIP},             // NSSW_LANGUAGE_TXT
       
   915 {    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,   206,   215, STR_0225,                         STR_NETWORK_LANGUAGE_TIP},             // NSSW_LANGUAGE_BTN
       
   916 
       
   917 /* Buttons Start / Load / Cancel */
       
   918 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    40,   140,   224,   235, STR_NETWORK_START_GAME,           STR_NETWORK_START_GAME_TIP},           // NSSW_START
       
   919 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   150,   250,   224,   235, STR_NETWORK_LOAD_GAME,            STR_NETWORK_LOAD_GAME_TIP},            // NSSW_LOAD
       
   920 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   260,   360,   224,   235, STR_012E_CANCEL,                  STR_NULL},                             // NSSW_CANCEL
       
   921 
   832 {   WIDGETS_END},
   922 {   WIDGETS_END},
   833 };
   923 };
   834 
   924 
   835 static const WindowDesc _network_start_server_window_desc = {
   925 static const WindowDesc _network_start_server_window_desc = {
   836 	WDP_CENTER, WDP_CENTER, 420, 244, 420, 244,
   926 	WDP_CENTER, WDP_CENTER, 420, 244, 420, 244,
   870 	}
   960 	}
   871 
   961 
   872 	return PLAYER_FIRST;
   962 	return PLAYER_FIRST;
   873 }
   963 }
   874 
   964 
   875 /* uses network_d WP macro */
   965 /** Enum for NetworkLobbyWindow, referring to _network_lobby_window_widgets */
       
   966 enum NetworkLobbyWindowWidgets {
       
   967 	NLWW_CLOSE    =  0, ///< Close 'X' button
       
   968 	NLWW_MATRIX   =  5, ///< List of companies
       
   969 	NLWW_DETAILS  =  7, ///< Company details
       
   970 	NLWW_JOIN     =  8, ///< 'Join company' button
       
   971 	NLWW_NEW      =  9, ///< 'New company' button
       
   972 	NLWW_SPECTATE = 10, ///< 'Spectate game' button
       
   973 	NLWW_REFRESH  = 11, ///< 'Refresh server' button
       
   974 	NLWW_CANCEL   = 12, ///< 'Cancel' button
       
   975 };
       
   976 
       
   977 /**
       
   978  * Handler of actions done in the NetworkLobby window
       
   979  *
       
   980  * @param w pointer to the Window structure
       
   981  * @param e pointer to window event
       
   982  * @note    uses network_d WP macro
       
   983  * @see     struct _network_lobby_window_widgets
       
   984  * @see     enum NetworkLobbyWindowWidgets
       
   985  */
   876 static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
   986 static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
   877 {
   987 {
   878 	network_d *nd = &WP(w, network_d);
   988 	network_d *nd = &WP(w, network_d);
   879 
   989 
   880 	switch (e->event) {
   990 	switch (e->event) {
   884 
   994 
   885 	case WE_PAINT: {
   995 	case WE_PAINT: {
   886 		const NetworkGameInfo *gi = &nd->server->info;
   996 		const NetworkGameInfo *gi = &nd->server->info;
   887 		int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
   997 		int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
   888 
   998 
   889 		SetWindowWidgetDisabledState(w, 7, nd->company == (byte)-1);
   999 		/* Join button is disabled when no company is selected */
   890 		SetWindowWidgetDisabledState(w, 8, gi->companies_on >= gi->companies_max);
  1000 		w->SetWidgetDisabledState(NLWW_JOIN, nd->company == INVALID_PLAYER);
   891 		/* You can not join a server as spectator when it has no companies active..
  1001 		/* Cannot start new company if there are too many */
   892 		 * it causes some nasty crashes */
  1002 		w->SetWidgetDisabledState(NLWW_NEW, gi->companies_on >= gi->companies_max);
   893 		SetWindowWidgetDisabledState(w, 9, gi->spectators_on >= gi->spectators_max ||
  1003 		/* Cannot spectate if there are too many spectators */
   894 				gi->companies_on == 0);
  1004 		w->SetWidgetDisabledState(NLWW_SPECTATE, gi->spectators_on >= gi->spectators_max);
   895 
  1005 
       
  1006 		/* Draw window widgets */
       
  1007 		SetDParamStr(0, gi->server_name);
   896 		DrawWindowWidgets(w);
  1008 		DrawWindowWidgets(w);
   897 
       
   898 		SetDParamStr(0, gi->server_name);
       
   899 		DrawString(10, 22, STR_NETWORK_PREPARE_TO_JOIN, 2);
       
   900 
  1009 
   901 		/* Draw company list */
  1010 		/* Draw company list */
   902 		pos = w->vscroll.pos;
  1011 		pos = w->vscroll.pos;
   903 		while (pos < gi->companies_on) {
  1012 		while (pos < gi->companies_on) {
   904 			byte company = NetworkLobbyFindCompanyIndex(pos);
  1013 			byte company = NetworkLobbyFindCompanyIndex(pos);
   905 			bool income = false;
  1014 			bool income = false;
   906 			if (nd->company == company)
  1015 			if (nd->company == company)
   907 				GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
  1016 				GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
   908 
  1017 
   909 			DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, 16, 135 - 13);
  1018 			DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, TC_BLACK, 135 - 13);
   910 			if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, 135, y);
  1019 			if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, PAL_NONE, 135, y);
   911 
  1020 
   912 			/* If the company's income was positive puts a green dot else a red dot */
  1021 			/* If the company's income was positive puts a green dot else a red dot */
   913 			if (_network_player_info[company].income >= 0) income = true;
  1022 			if (_network_player_info[company].income >= 0) income = true;
   914 			DrawSprite(SPR_BLOT, income ? PALETTE_TO_GREEN : PALETTE_TO_RED, 145, y);
  1023 			DrawSprite(SPR_BLOT, income ? PALETTE_TO_GREEN : PALETTE_TO_RED, 145, y);
   918 			if (pos >= w->vscroll.cap) break;
  1027 			if (pos >= w->vscroll.cap) break;
   919 		}
  1028 		}
   920 
  1029 
   921 		/* Draw info about selected company when it is selected in the left window */
  1030 		/* Draw info about selected company when it is selected in the left window */
   922 		GfxFillRect(174, 39, 403, 75, 157);
  1031 		GfxFillRect(174, 39, 403, 75, 157);
   923 		DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, 0);
  1032 		DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, TC_FROMSTRING);
   924 		if (nd->company != (byte)-1) {
  1033 		if (nd->company != INVALID_PLAYER) {
   925 			const uint x = 183;
  1034 			const uint x = 183;
   926 			const uint trunc_width = w->widget[6].right - x;
  1035 			const uint trunc_width = w->widget[NLWW_DETAILS].right - x;
   927 			y = 80;
  1036 			y = 80;
   928 
  1037 
   929 			SetDParam(0, nd->server->info.clients_on);
  1038 			SetDParam(0, nd->server->info.clients_on);
   930 			SetDParam(1, nd->server->info.clients_max);
  1039 			SetDParam(1, nd->server->info.clients_max);
   931 			SetDParam(2, nd->server->info.companies_on);
  1040 			SetDParam(2, nd->server->info.companies_on);
   932 			SetDParam(3, nd->server->info.companies_max);
  1041 			SetDParam(3, nd->server->info.companies_max);
   933 			DrawString(x, y, STR_NETWORK_CLIENTS, 2);
  1042 			DrawString(x, y, STR_NETWORK_CLIENTS, TC_GOLD);
   934 			y += 10;
  1043 			y += 10;
   935 
  1044 
   936 			SetDParamStr(0, _network_player_info[nd->company].company_name);
  1045 			SetDParamStr(0, _network_player_info[nd->company].company_name);
   937 			DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, 2, trunc_width);
  1046 			DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, TC_GOLD, trunc_width);
   938 			y += 10;
  1047 			y += 10;
   939 
  1048 
   940 			SetDParam(0, _network_player_info[nd->company].inaugurated_year);
  1049 			SetDParam(0, _network_player_info[nd->company].inaugurated_year);
   941 			DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, 2); // inauguration year
  1050 			DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, TC_GOLD); // inauguration year
   942 			y += 10;
  1051 			y += 10;
   943 
  1052 
   944 			SetDParam(0, _network_player_info[nd->company].company_value);
  1053 			SetDParam(0, _network_player_info[nd->company].company_value);
   945 			DrawString(x, y, STR_NETWORK_VALUE, 2); // company value
  1054 			DrawString(x, y, STR_NETWORK_VALUE, TC_GOLD); // company value
   946 			y += 10;
  1055 			y += 10;
   947 
  1056 
   948 			SetDParam(0, _network_player_info[nd->company].money);
  1057 			SetDParam(0, _network_player_info[nd->company].money);
   949 			DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, 2); // current balance
  1058 			DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, TC_GOLD); // current balance
   950 			y += 10;
  1059 			y += 10;
   951 
  1060 
   952 			SetDParam(0, _network_player_info[nd->company].income);
  1061 			SetDParam(0, _network_player_info[nd->company].income);
   953 			DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, 2); // last year's income
  1062 			DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, TC_GOLD); // last year's income
   954 			y += 10;
  1063 			y += 10;
   955 
  1064 
   956 			SetDParam(0, _network_player_info[nd->company].performance);
  1065 			SetDParam(0, _network_player_info[nd->company].performance);
   957 			DrawString(x, y, STR_NETWORK_PERFORMANCE, 2); // performance
  1066 			DrawString(x, y, STR_NETWORK_PERFORMANCE, TC_GOLD); // performance
   958 			y += 10;
  1067 			y += 10;
   959 
  1068 
   960 			SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
  1069 			SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
   961 			SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
  1070 			SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
   962 			SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
  1071 			SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
   963 			SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
  1072 			SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
   964 			SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
  1073 			SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
   965 			DrawString(x, y, STR_NETWORK_VEHICLES, 2); // vehicles
  1074 			DrawString(x, y, STR_NETWORK_VEHICLES, TC_GOLD); // vehicles
   966 			y += 10;
  1075 			y += 10;
   967 
  1076 
   968 			SetDParam(0, _network_player_info[nd->company].num_station[0]);
  1077 			SetDParam(0, _network_player_info[nd->company].num_station[0]);
   969 			SetDParam(1, _network_player_info[nd->company].num_station[1]);
  1078 			SetDParam(1, _network_player_info[nd->company].num_station[1]);
   970 			SetDParam(2, _network_player_info[nd->company].num_station[2]);
  1079 			SetDParam(2, _network_player_info[nd->company].num_station[2]);
   971 			SetDParam(3, _network_player_info[nd->company].num_station[3]);
  1080 			SetDParam(3, _network_player_info[nd->company].num_station[3]);
   972 			SetDParam(4, _network_player_info[nd->company].num_station[4]);
  1081 			SetDParam(4, _network_player_info[nd->company].num_station[4]);
   973 			DrawString(x, y, STR_NETWORK_STATIONS, 2); // stations
  1082 			DrawString(x, y, STR_NETWORK_STATIONS, TC_GOLD); // stations
   974 			y += 10;
  1083 			y += 10;
   975 
  1084 
   976 			SetDParamStr(0, _network_player_info[nd->company].players);
  1085 			SetDParamStr(0, _network_player_info[nd->company].players);
   977 			DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, 2, trunc_width); // players
  1086 			DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, TC_GOLD, trunc_width); // players
   978 		}
  1087 		}
   979 	} break;
  1088 	} break;
   980 
  1089 
   981 	case WE_CLICK:
  1090 	case WE_CLICK:
   982 		switch (e->we.click.widget) {
  1091 		switch (e->we.click.widget) {
   983 		case 0: case 11: /* Close 'X' | Cancel button */
  1092 		case NLWW_CLOSE:    // Close 'X'
       
  1093 		case NLWW_CANCEL:   // Cancel button
   984 			ShowNetworkGameWindow();
  1094 			ShowNetworkGameWindow();
   985 			break;
  1095 			break;
   986 		case 4: { /* Company list */
  1096 		case NLWW_MATRIX: { // Company list
   987 			uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
  1097 			uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
   988 
  1098 
   989 			if (id_v >= w->vscroll.cap) return;
  1099 			if (id_v >= w->vscroll.cap) break;
   990 
  1100 
   991 			id_v += w->vscroll.pos;
  1101 			id_v += w->vscroll.pos;
   992 			nd->company = (id_v >= nd->server->info.companies_on) ? INVALID_PLAYER : NetworkLobbyFindCompanyIndex(id_v);
  1102 			nd->company = (id_v >= nd->server->info.companies_on) ? INVALID_PLAYER : NetworkLobbyFindCompanyIndex(id_v);
   993 			SetWindowDirty(w);
  1103 			SetWindowDirty(w);
   994 		} break;
  1104 		} break;
   995 		case 7: /* Join company */
  1105 		case NLWW_JOIN:     // Join company
   996 			if (nd->company != (byte)-1) {
  1106 			/* Button can be clicked only when it is enabled */
   997 				_network_playas = nd->company;
  1107 			_network_playas = nd->company;
   998 				NetworkClientConnectGame(_network_last_host, _network_last_port);
  1108 			NetworkClientConnectGame(_network_last_host, _network_last_port);
   999 			}
  1109 			break;
  1000 			break;
  1110 		case NLWW_NEW:      // New company
  1001 		case 8: /* New company */
       
  1002 			_network_playas = PLAYER_NEW_COMPANY;
  1111 			_network_playas = PLAYER_NEW_COMPANY;
  1003 			NetworkClientConnectGame(_network_last_host, _network_last_port);
  1112 			NetworkClientConnectGame(_network_last_host, _network_last_port);
  1004 			break;
  1113 			break;
  1005 		case 9: /* Spectate game */
  1114 		case NLWW_SPECTATE: // Spectate game
  1006 			_network_playas = PLAYER_SPECTATOR;
  1115 			_network_playas = PLAYER_SPECTATOR;
  1007 			NetworkClientConnectGame(_network_last_host, _network_last_port);
  1116 			NetworkClientConnectGame(_network_last_host, _network_last_port);
  1008 			break;
  1117 			break;
  1009 		case 10: /* Refresh */
  1118 		case NLWW_REFRESH:  // Refresh
  1010 			NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
  1119 			NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
  1011 			NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
  1120 			NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
  1012 			break;
  1121 			break;
  1013 		} break;
  1122 		} break;
  1014 
  1123 
  1017 		break;
  1126 		break;
  1018 	}
  1127 	}
  1019 }
  1128 }
  1020 
  1129 
  1021 static const Widget _network_lobby_window_widgets[] = {
  1130 static const Widget _network_lobby_window_widgets[] = {
  1022 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                  STR_018B_CLOSE_WINDOW },
  1131 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                    STR_018B_CLOSE_WINDOW },           // NLWW_CLOSE
  1023 {    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_GAME_LOBBY,    STR_NULL},
  1132 {    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_GAME_LOBBY,      STR_NULL},
  1024 {      WWT_PANEL,   RESIZE_NONE,   BGC,     0,   419,    14,   234, 0x0,                       STR_NULL},
  1133 {      WWT_PANEL,   RESIZE_NONE,   BGC,     0,   419,    14,   234, 0x0,                         STR_NULL},
  1025 
  1134 {       WWT_TEXT,   RESIZE_NONE,   BGC,    10,   419,    22,    34, STR_NETWORK_PREPARE_TO_JOIN, STR_NULL},
  1026 // company list
  1135 
  1027 {      WWT_PANEL,   RESIZE_NONE,   BTC,    10,   155,    38,    49, 0x0,                       STR_NULL},
  1136 /* company list */
  1028 {     WWT_MATRIX,   RESIZE_NONE,   BGC,    10,   155,    50,   190, (10 << 8) + 1,             STR_NETWORK_COMPANY_LIST_TIP},
  1137 {      WWT_PANEL,   RESIZE_NONE,   BTC,    10,   155,    38,    49, 0x0,                         STR_NULL},
  1029 {  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   156,   167,    38,   190, STR_NULL,                  STR_0190_SCROLL_BAR_SCROLLS_LIST},
  1138 {     WWT_MATRIX,   RESIZE_NONE,   BGC,    10,   155,    50,   190, (10 << 8) + 1,               STR_NETWORK_COMPANY_LIST_TIP},     // NLWW_MATRIX
  1030 
  1139 {  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   156,   167,    38,   190, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST},
  1031 // company/player info
  1140 
  1032 {      WWT_PANEL,   RESIZE_NONE,   BGC,   173,   404,    38,   190, 0x0,                       STR_NULL},
  1141 /* company/player info */
  1033 
  1142 {      WWT_PANEL,   RESIZE_NONE,   BGC,   173,   404,    38,   190, 0x0,                         STR_NULL},                         // NLWW_DETAILS
  1034 // buttons
  1143 
  1035 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   151,   200,   211, STR_NETWORK_JOIN_COMPANY,  STR_NETWORK_JOIN_COMPANY_TIP},
  1144 /* buttons */
  1036 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   151,   215,   226, STR_NETWORK_NEW_COMPANY,   STR_NETWORK_NEW_COMPANY_TIP},
  1145 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   151,   200,   211, STR_NETWORK_JOIN_COMPANY,    STR_NETWORK_JOIN_COMPANY_TIP},     // NLWW_JOIN
  1037 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   158,   268,   200,   211, STR_NETWORK_SPECTATE_GAME, STR_NETWORK_SPECTATE_GAME_TIP},
  1146 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,    10,   151,   215,   226, STR_NETWORK_NEW_COMPANY,     STR_NETWORK_NEW_COMPANY_TIP},      // NLWW_NEW
  1038 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   158,   268,   215,   226, STR_NETWORK_REFRESH,       STR_NETWORK_REFRESH_TIP},
  1147 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   158,   268,   200,   211, STR_NETWORK_SPECTATE_GAME,   STR_NETWORK_SPECTATE_GAME_TIP},    // NLWW_SPECTATE
  1039 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   278,   388,   200,   211, STR_012E_CANCEL,           STR_NULL},
  1148 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   158,   268,   215,   226, STR_NETWORK_REFRESH,         STR_NETWORK_REFRESH_TIP},          // NLWW_REFRESH
       
  1149 { WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   278,   388,   200,   211, STR_012E_CANCEL,             STR_NULL},                         // NLWW_CANCEL
  1040 
  1150 
  1041 {   WIDGETS_END},
  1151 {   WIDGETS_END},
  1042 };
  1152 };
  1043 
  1153 
  1044 static const WindowDesc _network_lobby_window_desc = {
  1154 static const WindowDesc _network_lobby_window_desc = {
  1309 static void ClientListPopupWndProc(Window *w, WindowEvent *e)
  1419 static void ClientListPopupWndProc(Window *w, WindowEvent *e)
  1310 {
  1420 {
  1311 	switch (e->event) {
  1421 	switch (e->event) {
  1312 	case WE_PAINT: {
  1422 	case WE_PAINT: {
  1313 		int i, y, sel;
  1423 		int i, y, sel;
  1314 		byte colour;
  1424 		TextColour colour;
  1315 		DrawWindowWidgets(w);
  1425 		DrawWindowWidgets(w);
  1316 
  1426 
  1317 		// Draw the actions
  1427 		// Draw the actions
  1318 		sel = WP(w,menu_d).sel_index;
  1428 		sel = WP(w,menu_d).sel_index;
  1319 		y = 1;
  1429 		y = 1;
  1321 			if (_clientlist_action[i][0] == '\0') continue;
  1431 			if (_clientlist_action[i][0] == '\0') continue;
  1322 			if (_clientlist_proc[i] == NULL) continue;
  1432 			if (_clientlist_proc[i] == NULL) continue;
  1323 
  1433 
  1324 			if (sel-- == 0) { // Selected item, highlight it
  1434 			if (sel-- == 0) { // Selected item, highlight it
  1325 				GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
  1435 				GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
  1326 				colour = 0xC;
  1436 				colour = TC_WHITE;
  1327 			} else {
  1437 			} else {
  1328 				colour = 0x10;
  1438 				colour = TC_BLACK;
  1329 			}
  1439 			}
  1330 
  1440 
  1331 			DoDrawString(_clientlist_action[i], 4, y, colour);
  1441 			DoDrawString(_clientlist_action[i], 4, y, colour);
  1332 		}
  1442 		}
  1333 	} break;
  1443 	} break;
  1360 {
  1470 {
  1361 	switch (e->event) {
  1471 	switch (e->event) {
  1362 	case WE_PAINT: {
  1472 	case WE_PAINT: {
  1363 		NetworkClientInfo *ci;
  1473 		NetworkClientInfo *ci;
  1364 		int y, i = 0;
  1474 		int y, i = 0;
  1365 		byte colour;
  1475 		TextColour colour;
  1366 
  1476 
  1367 		// Check if we need to reset the height
  1477 		// Check if we need to reset the height
  1368 		if (!CheckClientListHeight(w)) break;
  1478 		if (!CheckClientListHeight(w)) break;
  1369 
  1479 
  1370 		DrawWindowWidgets(w);
  1480 		DrawWindowWidgets(w);
  1372 		y = CLNWND_OFFSET;
  1482 		y = CLNWND_OFFSET;
  1373 
  1483 
  1374 		FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
  1484 		FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
  1375 			if (_selected_clientlist_item == i++) { // Selected item, highlight it
  1485 			if (_selected_clientlist_item == i++) { // Selected item, highlight it
  1376 				GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
  1486 				GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
  1377 				colour = 0xC;
  1487 				colour = TC_WHITE;
  1378 			} else {
  1488 			} else {
  1379 				colour = 0x10;
  1489 				colour = TC_BLACK;
  1380 			}
  1490 			}
  1381 
  1491 
  1382 			if (ci->client_index == NETWORK_SERVER_INDEX) {
  1492 			if (ci->client_index == NETWORK_SERVER_INDEX) {
  1383 				DrawString(4, y, STR_NETWORK_SERVER, colour);
  1493 				DrawString(4, y, STR_NETWORK_SERVER, colour);
  1384 			} else {
  1494 			} else {
  1461 	switch (e->event) {
  1571 	switch (e->event) {
  1462 	case WE_PAINT: {
  1572 	case WE_PAINT: {
  1463 		uint8 progress; // used for progress bar
  1573 		uint8 progress; // used for progress bar
  1464 		DrawWindowWidgets(w);
  1574 		DrawWindowWidgets(w);
  1465 
  1575 
  1466 		DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, 14);
  1576 		DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, TC_GREY);
  1467 		switch (_network_join_status) {
  1577 		switch (_network_join_status) {
  1468 			case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
  1578 			case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
  1469 			case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
  1579 			case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
  1470 				progress = 10; // first two stages 10%
  1580 				progress = 10; // first two stages 10%
  1471 				break;
  1581 				break;
  1472 			case NETWORK_JOIN_STATUS_WAITING:
  1582 			case NETWORK_JOIN_STATUS_WAITING:
  1473 				SetDParam(0, _network_join_waiting);
  1583 				SetDParam(0, _network_join_waiting);
  1474 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, 14);
  1584 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, TC_GREY);
  1475 				progress = 15; // third stage is 15%
  1585 				progress = 15; // third stage is 15%
  1476 				break;
  1586 				break;
  1477 			case NETWORK_JOIN_STATUS_DOWNLOADING:
  1587 			case NETWORK_JOIN_STATUS_DOWNLOADING:
  1478 				SetDParam(0, _network_join_kbytes);
  1588 				SetDParam(0, _network_join_kbytes);
  1479 				SetDParam(1, _network_join_kbytes_total);
  1589 				SetDParam(1, _network_join_kbytes_total);
  1480 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, 14);
  1590 				DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, TC_GREY);
  1481 				/* Fallthrough */
  1591 				/* Fallthrough */
  1482 			default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
  1592 			default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
  1483 				progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
  1593 				progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
  1484 		}
  1594 		}
  1485 
  1595 
  1683  */
  1793  */
  1684 static void ChatWindowWndProc(Window *w, WindowEvent *e)
  1794 static void ChatWindowWndProc(Window *w, WindowEvent *e)
  1685 {
  1795 {
  1686 	switch (e->event) {
  1796 	switch (e->event) {
  1687 	case WE_CREATE:
  1797 	case WE_CREATE:
  1688 		SendWindowMessage(WC_NEWS_WINDOW, 0, WE_CREATE, w->height, 0);
       
  1689 		SETBIT(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
       
  1690 		break;
  1798 		break;
  1691 
  1799 
  1692 	case WE_PAINT: {
  1800 	case WE_PAINT: {
  1693 		static const StringID chat_captions[] = {
       
  1694 			STR_NETWORK_CHAT_ALL_CAPTION,
       
  1695 			STR_NETWORK_CHAT_COMPANY_CAPTION,
       
  1696 			STR_NETWORK_CHAT_CLIENT_CAPTION
       
  1697 		};
       
  1698 		StringID msg;
       
  1699 
       
  1700 		DrawWindowWidgets(w);
  1801 		DrawWindowWidgets(w);
  1701 
  1802 
  1702 		assert(WP(w, chatquerystr_d).caption < lengthof(chat_captions));
       
  1703 		msg = chat_captions[WP(w, chatquerystr_d).caption];
       
  1704 		DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, msg, 16);
       
  1705 		DrawEditBox(w, &WP(w, chatquerystr_d), 2);
  1803 		DrawEditBox(w, &WP(w, chatquerystr_d), 2);
  1706 	} break;
  1804 	} break;
  1707 
  1805 
  1708 	case WE_CLICK:
  1806 	case WE_CLICK:
  1709 		switch (e->we.click.widget) {
  1807 		switch (e->we.click.widget) {
  1736 		}
  1834 		}
  1737 		break;
  1835 		break;
  1738 
  1836 
  1739 	case WE_DESTROY:
  1837 	case WE_DESTROY:
  1740 		SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
  1838 		SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
  1741 		CLRBIT(_no_scroll, SCROLL_CHAT);
  1839 		ClrBit(_no_scroll, SCROLL_CHAT);
  1742 		break;
  1840 		break;
  1743 	}
  1841 	}
  1744 }
  1842 }
  1745 
  1843 
  1746 static const Widget _chat_window_widgets[] = {
  1844 static const Widget _chat_window_widgets[] = {
  1768 	_edit_str_buf[0] = '\0';
  1866 	_edit_str_buf[0] = '\0';
  1769 	_chat_tab_completion_active = false;
  1867 	_chat_tab_completion_active = false;
  1770 
  1868 
  1771 	w = AllocateWindowDesc(&_chat_window_desc);
  1869 	w = AllocateWindowDesc(&_chat_window_desc);
  1772 
  1870 
  1773 	LowerWindowWidget(w, 2);
  1871 	w->LowerWidget(2);
  1774 	WP(w, chatquerystr_d).caption = type; // Misuse of caption
  1872 	WP(w, chatquerystr_d).caption = type; // Misuse of caption
  1775 	WP(w, chatquerystr_d).dest    = dest;
  1873 	WP(w, chatquerystr_d).dest    = dest;
  1776 	WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
  1874 	WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
  1777 	InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 0);
  1875 	InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 0);
  1778 }
  1876 }
  1779 
  1877 
       
  1878 /** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
       
  1879 enum NetworkCompanyPasswordWindowWidgets {
       
  1880 	NCPWW_CLOSE,                    ///< Close 'X' button
       
  1881 	NCPWW_CAPTION,                  ///< Caption of the whole window
       
  1882 	NCPWW_BACKGROUND,               ///< The background of the interface
       
  1883 	NCPWW_LABEL,                    ///< Label in front of the password field
       
  1884 	NCPWW_PASSWORD,                 ///< Input field for the password
       
  1885 	NCPWW_SAVE_AS_DEFAULT_PASSWORD, ///< Toggle 'button' for saving the current password as default password
       
  1886 	NCPWW_CANCEL,                   ///< Close the window without changing anything
       
  1887 	NCPWW_OK,                       ///< Safe the password etc.
       
  1888 };
       
  1889 
       
  1890 static void NetworkCompanyPasswordWindowWndProc(Window *w, WindowEvent *e)
       
  1891 {
       
  1892 	switch (e->event) {
       
  1893 		case WE_PAINT:
       
  1894 			DrawWindowWidgets(w);
       
  1895 			DrawEditBox(w, &WP(w, chatquerystr_d), 4);
       
  1896 			break;
       
  1897 
       
  1898 		case WE_CLICK:
       
  1899 			switch (e->we.click.widget) {
       
  1900 				case NCPWW_OK: {
       
  1901 					if (w->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
       
  1902 						snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", _edit_str_buf);
       
  1903 					}
       
  1904 
       
  1905 					/* empty password is a '*' because of console argument */
       
  1906 					if (StrEmpty(_edit_str_buf)) snprintf(_edit_str_buf, lengthof(_edit_str_buf), "*");
       
  1907 					char *password = _edit_str_buf;
       
  1908 					NetworkChangeCompanyPassword(1, &password);
       
  1909 				}
       
  1910 
       
  1911 				/* FALL THROUGH */
       
  1912 				case NCPWW_CANCEL:
       
  1913 					DeleteWindow(w);
       
  1914 					break;
       
  1915 
       
  1916 				case NCPWW_SAVE_AS_DEFAULT_PASSWORD:
       
  1917 					w->ToggleWidgetLoweredState(NCPWW_SAVE_AS_DEFAULT_PASSWORD);
       
  1918 					SetWindowDirty(w);
       
  1919 					break;
       
  1920 			}
       
  1921 			break;
       
  1922 
       
  1923 		case WE_MOUSELOOP:
       
  1924 			HandleEditBox(w, &WP(w, chatquerystr_d), 4);
       
  1925 			break;
       
  1926 
       
  1927 		case WE_KEYPRESS:
       
  1928 			switch (HandleEditBoxKey(w, &WP(w, chatquerystr_d), 4, e)) {
       
  1929 				case 1: // Return
       
  1930 					/* FALLTHROUGH */
       
  1931 				case 2: // Escape
       
  1932 					DeleteWindow(w);
       
  1933 					break;
       
  1934 			}
       
  1935 			break;
       
  1936 	}
       
  1937 }
       
  1938 
       
  1939 static const Widget _ncp_window_widgets[] = {
       
  1940 {   WWT_CLOSEBOX, RESIZE_NONE, 14,   0,  10,  0, 13, STR_00C5,                          STR_018B_CLOSE_WINDOW},
       
  1941 {    WWT_CAPTION, RESIZE_NONE, 14,  11, 299,  0, 13, STR_COMPANY_PASSWORD_CAPTION,      STR_018C_WINDOW_TITLE_DRAG_THIS},
       
  1942 {      WWT_PANEL, RESIZE_NONE, 14,   0, 299, 14, 50, 0x0,                               STR_NULL},
       
  1943 {       WWT_TEXT, RESIZE_NONE, 14,   5, 100, 19, 30, STR_COMPANY_PASSWORD,              STR_NULL},
       
  1944 {      WWT_PANEL, RESIZE_NONE, 14, 101, 294, 19, 30, 0x0,                               STR_NULL},
       
  1945 {    WWT_TEXTBTN, RESIZE_NONE, 14, 101, 294, 35, 46, STR_MAKE_DEFAULT_COMPANY_PASSWORD, STR_MAKE_DEFAULT_COMPANY_PASSWORD_TIP},
       
  1946 { WWT_PUSHTXTBTN, RESIZE_NONE, 14,   0, 149, 51, 62, STR_012E_CANCEL,                   STR_COMPANY_PASSWORD_CANCEL},
       
  1947 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 150, 299, 51, 62, STR_012F_OK,                       STR_COMPANY_PASSWORD_OK},
       
  1948 {   WIDGETS_END},
       
  1949 };
       
  1950 
       
  1951 static const WindowDesc _ncp_window_desc = {
       
  1952 	WDP_AUTO, WDP_AUTO, 300, 63, 300, 63,
       
  1953 	WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
       
  1954 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
       
  1955 	_ncp_window_widgets,
       
  1956 	NetworkCompanyPasswordWindowWndProc
       
  1957 };
       
  1958 
       
  1959 void ShowNetworkCompanyPasswordWindow()
       
  1960 {
       
  1961 	DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0);
       
  1962 
       
  1963 	_edit_str_buf[0] = '\0';
       
  1964 	Window *w = AllocateWindowDesc(&_ncp_window_desc);
       
  1965 	WP(w, chatquerystr_d).afilter = CS_ALPHANUMERAL;
       
  1966 	InitializeTextBuffer(&WP(w, chatquerystr_d).text, _edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(_edit_str_buf)), 0);
       
  1967 }
       
  1968 
  1780 #endif /* ENABLE_NETWORK */
  1969 #endif /* ENABLE_NETWORK */