CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

NETDLG.CPP (211680B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\netdlg.cpv   2.17   16 Oct 1995 16:52:26   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                         						  *
     21  *                 Project Name : Command & Conquer                        						  *
     22  *                                                                         						  *
     23  *                    File Name : NETDLG.CPP                               						  *
     24  *                                                                         						  *
     25  *                   Programmer : Bill Randolph                            						  *
     26  *                                                                         						  *
     27  *                   Start Date : January 23, 1995                         						  *
     28  *                                                                         						  *
     29  *                  Last Update : July 8, 1995 [BRR]                       						  *
     30  *                                                                         						  *
     31  *---------------------------------------------------------------------------------------------*
     32  *                                                                         						  *
     33  * These routines establish & maintain peer-to-peer connections between this system				  *
     34  * and all others in the game.  Each system finds out the IPX address of the others,			  *
     35  * and forms a direct connection (IPXConnectionClass) to that system.  Systems are				  *
     36  * found out via broadcast queries.  Every system broadcasts its queries, and every				  *
     37  * system replies to queries it receives.  At the point when the game owner signals				  *
     38  * 'OK', every system must know about all the other systems in the game.							  *
     39  *                                                                         						  *
     40  * How Bridges are handled:																						  *
     41  * Currently, bridges are handled by specifying the destination IPX address of the				  *
     42  * "server" (game owner's system) on the command-line.  This address is used to					  *
     43  * derive a broadcast address to that destination network, and this system's queries			  *
     44  * are broadcast over its network & the server's network; replies to the queries come			  *
     45  * with each system's IPX address attached, so once we have the address, we can form			  *
     46  * a connection with any system on the bridged net.														  *
     47  *                                                                         						  *
     48  * The flaw in this plan is that we can only cross one bridge.  If there are 3 nets				  *
     49  * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts			  *
     50  * will reach nets A & B, but not C.  The way to circumvent this (if it becomes a problem)	  *
     51  * would be to have the server tell us what other systems are in its game, not each				  *
     52  * individual player's system.  Thus, each system would find out about all the other systems	  *
     53  * by interacting with the game's owner system (this would be more involved than what			  *
     54  * I'm doing here).																									  *
     55  *                                                                         						  *
     56  * Here's a list of all the different packets sent over the Global Channel:						  *
     57  *																															  *
     58  *	NET_QUERY_GAME																										  *
     59  *							(no other data)																			  *
     60  *	NET_ANSWER_GAME																									  *
     61  *							Name:					game owner's name													  *
     62  *							GameInfo:			game's version & open state									  *
     63  *	NET_QUERY_PLAYER																									  *
     64  *							Name:					name of game we want players to respond for				  *
     65  *	NET_ANSWER_PLAYER																									  *
     66  *							Name:					player's name														  *
     67  *							PlayerInfo:			info about player													  *
     68  *	NET_QUERY_JOIN																										  *
     69  *							Name:					name of player wanting to join								  *
     70  *							PlayerInfo:			player's requested house & color								  *
     71  *	NET_CONFIRM_JOIN																									  *
     72  *							PlayerInfo:			approves player's house & color								  *
     73  *	NET_REJECT_JOIN																									  *
     74  *							(no other data)																			  *
     75  *	NET_GAME_OPTIONS																									  *
     76  *							ScenarioInfo:		info about scenario												  *
     77  *	NET_SIGN_OFF																										  *
     78  *							Name:					name of player signing off										  *
     79  *	NET_PING																												  *
     80  *							(no other data)																			  *
     81  *	NET_GO																												  *
     82  *							Delay:            value of one-way response time, in frames               *
     83  * 																														  *
     84  *---------------------------------------------------------------------------------------------*
     85  * Functions:                                                              						  *
     86  *   Clear_Game_List -- Clears the game-name listbox & 'Games' Vector        						  *
     87  *   Clear_Player_List -- Clears the player-name listbox & Vector     		   					  *
     88  *   Destroy_Connection -- destroys the given connection													  *
     89  *   Get_Join_Responses -- sends queries for the Join Dialog											  *
     90  *   Get_NewGame_Responses -- processes packets for New Game dialog                            *
     91  *   Init_Network -- initializes network stuff                             						  *
     92  *   Net_Join_Dialog -- lets user join an existing game, or start a new one						  *
     93  *   Net_New_Dialog -- lets user start a new game															  *
     94  *   Process_Global_Packet -- responds to remote queries                   						  *
     95  *   Remote_Connect -- handles connecting this user to others              						  *
     96  *   Request_To_Join -- Sends a JOIN request packet to game owner           	 					  *
     97  *   Send_Join_Queries -- sends queries for the Join Dialog												  *
     98  *   Shutdown_Network -- shuts down network stuff                          						  *
     99  *   Compute_Name_CRC -- computes CRC from char string                                         *
    100  *   Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog                        *
    101  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    102 
    103 #include "function.h"
    104 #include <time.h>
    105 #include "tcpip.h"
    106 #include "ccdde.h"
    107 #define SHOW_MONO		0
    108 
    109 // ST = 12/17/2018 5:44PM
    110 #ifndef TickCount
    111 extern TimerClass					TickCount;
    112 #endif
    113 
    114 #ifndef DEMO
    115 
    116 /*---------------------------------------------------------------------------
    117 The possible states of the join-game dialog
    118 ---------------------------------------------------------------------------*/
    119 typedef enum {
    120 	JOIN_REJECTED = -1,		// we've been rejected
    121 	JOIN_NOTHING,				// we're not trying to join a game
    122 	JOIN_WAIT_CONFIRM,		// we're asking to join, & waiting for confirmation
    123 	JOIN_CONFIRMED,			// we've been confirmed
    124 	JOIN_GAME_START,			// the game we've joined is starting
    125 } JoinStateType;
    126 
    127 /*---------------------------------------------------------------------------
    128 The possible return codes from Get_Join_Responses()
    129 ---------------------------------------------------------------------------*/
    130 typedef enum {
    131 	EV_NONE,							// nothing happened
    132 	EV_STATE_CHANGE,				// Join dialog is in a new state
    133 	EV_NEW_GAME,					// a new game was detected
    134 	EV_NEW_PLAYER,					// a new player was detected
    135 	EV_PLAYER_SIGNOFF,			// a player has signed off
    136 	EV_GAME_SIGNOFF,				// a gamed owner has signed off
    137 	EV_GAME_OPTIONS,				// a game options packet was received
    138 	EV_MESSAGE,						// a message was received
    139 } JoinEventType;
    140 
    141 
    142 /*
    143 ******************************** Prototypes *********************************
    144 */
    145 static int Net_Join_Dialog(void);
    146 static void Clear_Game_List (ListClass *gamelist);
    147 static void Clear_Player_List (ListClass *playerlist);
    148 static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
    149 	HousesType house, int color);
    150 static void Send_Join_Queries(int curgame, int gamenow, int playernow);
    151 static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
    152 	ColorListClass *playerlist, int join_index);
    153 static int Net_New_Dialog(void);
    154 static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist);
    155 static int Net_Fake_New_Dialog(void);
    156 static int Net_Fake_Join_Dialog(void);
    157 
    158 
    159 /***********************************************************************************************
    160  * Init_Network -- initializes network stuff                               						  *
    161  *                                                                         						  *
    162  * INPUT:                                                                  						  *
    163  *		none.																												  *
    164  *                                                                         						  *
    165  * OUTPUT:                                                                 						  *
    166  *		true = Initialization OK, false = error																  *
    167  *                                                                         						  *
    168  * WARNINGS:                                                               						  *
    169  *		none.																												  *
    170  *                                                                         						  *
    171  * HISTORY:                                                                						  *
    172  *   02/14/1995 BR : Created.                                              						  *
    173  *=============================================================================================*/
    174 bool Init_Network (void)
    175 {
    176 	NetNumType net;
    177 	NetNodeType node;
    178 
    179 	/*------------------------------------------------------------------------
    180 	This call allocates all necessary queue buffers, allocates Real-mode
    181 	memory, and commands IPX to start listening on the Global Channel.
    182 	------------------------------------------------------------------------*/
    183 	if (!Ipx.Init())
    184 		return(false);
    185 
    186 	/*------------------------------------------------------------------------
    187 	Allocate our "meta-packet" buffer
    188 	------------------------------------------------------------------------*/
    189 	if (!MetaPacket) {
    190 		MetaPacket = new char [sizeof (EventClass) * MAX_EVENTS];
    191 	}
    192 
    193 	/*------------------------------------------------------------------------
    194 	Set up the IPX manager to cross a bridge
    195 	------------------------------------------------------------------------*/
    196 	if (!(GameToPlay == GAME_INTERNET)){
    197 		if (IsBridge) {
    198 			BridgeNet.Get_Address(net,node);
    199 			Ipx.Set_Bridge(net);
    200 		}
    201 	}
    202 
    203 	return(true);
    204 
    205 }	/* end of Init_Network */
    206 
    207 
    208 /***********************************************************************************************
    209  * Shutdown_Network -- shuts down network stuff                            						  *
    210  *                                                                         						  *
    211  * INPUT:                                                                  						  *
    212  *		none.																												  *
    213  *                                                                         						  *
    214  * OUTPUT:                                                                 						  *
    215  *		none.																												  *
    216  *                                                                         						  *
    217  * WARNINGS:                                                               						  *
    218  *		none.																												  *
    219  *                                                                         						  *
    220  * HISTORY:                                                                						  *
    221  *   02/14/1995 BR : Created.                                              						  *
    222  *=============================================================================================*/
    223 void Shutdown_Network (void)
    224 {
    225 
    226 //
    227 // Note: The thought behind this section of code was that if the program
    228 // terminates early, without an EventClass::EXIT event, it still needs to
    229 // tell the other systems that it's gone, so it would send a SIGN_OFF packet.
    230 // BUT, this causes a sync bug if the systems are running slow and this system
    231 // is running ahead of the others; it will send the NET_SIGN_OFF >>before<<
    232 // the other system execute their EventClass::EXIT event, and the other systems
    233 // will kill the connection at some random Frame # & turn my stuff over to
    234 // the computer possibly at different times.
    235 // BRR, 10/29/96
    236 //
    237 #if (0)
    238 	/*------------------------------------------------------------------------
    239 	Broadcast a sign-off packet, by sending the packet over the Global Channel,
    240 	telling the IPX Manager that no ACK is required, and specifying a NULL
    241 	destination address.
    242 	------------------------------------------------------------------------*/
    243 	memset (&GPacket, 0, sizeof(GlobalPacketType));
    244 
    245 	GPacket.Command = NET_SIGN_OFF;
    246 	strcpy (GPacket.Name, MPlayerName);
    247 
    248 	Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
    249 	Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
    250 
    251 	if (IsBridge && !Winsock.Get_Connected()) {
    252 		Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
    253 		Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
    254 	}
    255 
    256 	/*------------------------------------------------------------------------
    257 	Wait for the packets to finish going out (or the Global Channel times out)
    258 	------------------------------------------------------------------------*/
    259 	for (;;) {
    260 		if (Ipx.Global_Num_Send()==0) {
    261 			break;
    262 		}
    263 		Ipx.Service();
    264 	}
    265 
    266 #endif	//(0)
    267 
    268 	/*------------------------------------------------------------------------
    269 	Delete our "meta-packet"
    270 	------------------------------------------------------------------------*/
    271 	delete [] MetaPacket;
    272 	MetaPacket = 0;
    273 
    274 	/*------------------------------------------------------------------------
    275 	If I was in a game, I'm not now, so clear the game name
    276 	------------------------------------------------------------------------*/
    277 	MPlayerGameName[0] = 0;
    278 }
    279 
    280 
    281 /***********************************************************************************************
    282  * Process_Global_Packet -- responds to remote queries                     						  *
    283  *                                                                         						  *
    284  * The only commands from other systems this routine responds to are NET_QUERY_GAME				  *
    285  * and NET_QUERY_PLAYER.  The other commands are too context-specific to be able					  *
    286  * to handle here, such as joining the game or signing off; but this routine handles			  *
    287  * the majority of the program's needs.																		  *
    288  *                                                                         						  *
    289  * INPUT:                                                                  						  *
    290  *		packet		ptr to packet to process																	  *
    291  *		address		source address of sender																	  *
    292  *                                                                         						  *
    293  * OUTPUT:                                                                 						  *
    294  *		true = packet was processed, false = wasn't															  *
    295  *                                                                         						  *
    296  * WARNINGS:                                                               						  *
    297  *		MPlayerName & MPlayerGameName must have been filled in before this function				  *
    298  *		can be called.																									  *
    299  *                                                                         						  *
    300  * HISTORY:                                                                						  *
    301  *   02/15/1995 BR : Created.                                              						  *
    302  *=============================================================================================*/
    303 bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)
    304 {
    305 	GlobalPacketType mypacket;
    306 
    307 	/*
    308 	---------------- Another system asking what game this is -----------------
    309 	*/
    310 	if (packet->Command==NET_QUERY_GAME && NetStealth==0) {
    311 		/*.....................................................................
    312 		If the game is closed, let every player respond, and let the sender of
    313 		the query sort it all out.  This way, if the game's host exits the game,
    314 		the game still shows up on other players' dialogs.
    315 		If the game is open, only the game owner may respond.
    316 		.....................................................................*/
    317 		if (strlen(MPlayerName) > 0 && strlen(MPlayerGameName) > 0 &&
    318 			((!NetOpen) || (NetOpen && !strcmp(MPlayerName,MPlayerGameName)))) {
    319 			memset (packet, 0, sizeof(GlobalPacketType));
    320 
    321 			mypacket.Command = NET_ANSWER_GAME;
    322 			strcpy(mypacket.Name, MPlayerGameName);
    323 #ifdef PATCH
    324 			if (IsV107) {
    325 				mypacket.GameInfo.Version = 1;
    326 			} else {
    327 				mypacket.GameInfo.Version = 2;
    328 			}
    329 #else
    330 			mypacket.GameInfo.Version = Version_Number();
    331 #endif
    332 			mypacket.GameInfo.IsOpen = NetOpen;
    333 
    334 			Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,
    335 				address);
    336 		}
    337 		return(true);
    338 	} else {
    339 
    340 		/*
    341 		----------------- Another system asking what player I am -----------------
    342 		*/
    343 		if (packet->Command==NET_QUERY_PLAYER &&
    344 			!strcmp (packet->Name, MPlayerGameName) &&
    345 				(strlen(MPlayerGameName) > 0) && NetStealth==0) {
    346 			memset (packet, 0, sizeof(GlobalPacketType));
    347 
    348 			mypacket.Command = NET_ANSWER_PLAYER;
    349 			strcpy(mypacket.Name, MPlayerName);
    350 			mypacket.PlayerInfo.House = MPlayerHouse;
    351 			mypacket.PlayerInfo.Color = MPlayerColorIdx;
    352 			mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(MPlayerGameName);
    353 
    354 			Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);
    355 			return(true);
    356 		}
    357 	}
    358 	return(false);
    359 }
    360 
    361 
    362 /***********************************************************************************************
    363  * Destroy_Connection -- destroys the given connection													  *
    364  *                                                                         						  *
    365  * Call this routine when a connection goes bad, or another player signs off.						  *
    366  *                                                                         						  *
    367  * INPUT:                                                                  						  *
    368  *		id			connection ID to destroy																		  *
    369  *		error		0 = user signed off; 1 = connection error; otherwise, no error is shown.		  *
    370  *                                                                         						  *
    371  * OUTPUT:                                                                 						  *
    372  *		none.																												  *
    373  *                                                                         						  *
    374  * WARNINGS:                                                               						  *
    375  *		none.																												  *
    376  *                                                                         						  *
    377  * HISTORY:                                                                						  *
    378  *   04/22/1995 BR : Created.                                              						  *
    379  *=============================================================================================*/
    380 void Destroy_Connection(int id, int error)
    381 {
    382 	int i,j;
    383 	HousesType house;
    384 	HouseClass *housep;
    385 	char txt[80];
    386 
    387 	/*------------------------------------------------------------------------
    388 	Create a message to display to the user
    389 	------------------------------------------------------------------------*/
    390 	txt[0] = '\0';
    391 	if (error==1) {
    392 		sprintf(txt,Text_String(TXT_CONNECTION_LOST),Ipx.Connection_Name(id));
    393 	} else if (error==0) {
    394 		sprintf(txt,Text_String(TXT_LEFT_GAME),Ipx.Connection_Name(id));
    395 	}
    396 
    397 	if (strlen(txt)) {
    398 		Messages.Add_Message (txt,
    399 			MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
    400 			TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
    401 		Map.Flag_To_Redraw(false);
    402 	}
    403 
    404 	/*------------------------------------------------------------------------
    405 	Delete the IPX connection, shift the MPlayerID's & MPlayerHouses' back one.
    406 	------------------------------------------------------------------------*/
    407 	Ipx.Delete_Connection(id);
    408 
    409 	for (i = 0; i < MPlayerCount; i++) {
    410 		if (MPlayerID[i] == (unsigned char)id) {
    411 			/*..................................................................
    412 			Turn the player's house over to the computer's AI
    413 			..................................................................*/
    414 			house = MPlayerHouses[i];
    415 			housep = HouseClass::As_Pointer (house);
    416 			housep->IsHuman = false;
    417 			housep->IsStarted = true;
    418 
    419 			/*..................................................................
    420 			Move arrays back by one
    421 			..................................................................*/
    422 			for (j = i; j < MPlayerCount - 1; j++) {
    423 				MPlayerID[j] = MPlayerID[j + 1];
    424 				MPlayerHouses[j] = MPlayerHouses[j + 1];
    425 				strcpy (MPlayerNames[j], MPlayerNames[j+1]);
    426 				TheirProcessTime[j] = TheirProcessTime[j+1];
    427 			}
    428 		}
    429 	}
    430 
    431 	MPlayerCount--;
    432 
    433 	/*------------------------------------------------------------------------
    434 	If we're the last player left, tell the user.
    435 	------------------------------------------------------------------------*/
    436 	if (MPlayerCount == 1) {
    437 		sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
    438 		Messages.Add_Message (txt,
    439 			MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
    440 			TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
    441 		Map.Flag_To_Redraw(false);
    442 	}
    443 
    444 }	/* end of Destroy_Connection */
    445 
    446 
    447 /***********************************************************************************************
    448  * Remote_Connect -- handles connecting this user to others                						  *
    449  *                                                                         						  *
    450  * INPUT:                                                                  						  *
    451  *		none.																												  *
    452  *                                                                         						  *
    453  * OUTPUT:                                                                 						  *
    454  *		true = connections established; false = not															  *
    455  *                                                                         						  *
    456  * WARNINGS:                                                               						  *
    457  *		none.																												  *
    458  *                                                                         						  *
    459  * HISTORY:                                                                						  *
    460  *   02/14/1995 BR : Created.                                              						  *
    461  *=============================================================================================*/
    462 bool Remote_Connect(void)
    463 {
    464 	int rc;
    465 	int stealth;				// original state of NetStealth flag
    466 
    467 	/*------------------------------------------------------------------------
    468 	Init network timing parameters; these values should work for both a "real"
    469 	network, and a simulated modem network (ie Kali)
    470 	------------------------------------------------------------------------*/
    471 	Ipx.Set_Timing (	30, 		// retry 2 times per second
    472 							-1, 		// ignore max retries
    473 							600);		// give up after 10 seconds
    474 
    475 	/*------------------------------------------------------------------------
    476 	Save the original value of the NetStealth flag, so we can turn stealth
    477 	off for now (during this portion of the dialogs, we must show ourselves)
    478 	------------------------------------------------------------------------*/
    479 	stealth = NetStealth;
    480 	NetStealth = 0;
    481 
    482 	/*------------------------------------------------------------------------
    483 	Init my game name to 0-length, since I haven't joined any game yet.
    484 	------------------------------------------------------------------------*/
    485 	MPlayerGameName[0] = 0;
    486 
    487 	/*------------------------------------------------------------------------
    488 	The game is now "open" for joining.  Close it as soon as we exit this
    489 	routine.
    490 	------------------------------------------------------------------------*/
    491 	NetOpen = 1;
    492 
    493 	/*------------------------------------------------------------------------
    494 	Read the default values from the INI file
    495 	------------------------------------------------------------------------*/
    496 	Read_MultiPlayer_Settings ();
    497 
    498 	/*------------------------------------------------------------------------
    499 	Keep looping until something useful happens.
    500 	------------------------------------------------------------------------*/
    501 	while (1) {
    502 		/*---------------------------------------------------------------------
    503 		Pop up the network Join/New dialog
    504 		---------------------------------------------------------------------*/
    505 		rc = Net_Join_Dialog();
    506 
    507 		/*---------------------------------------------------------------------
    508 		-1 = user selected Cancel
    509 		---------------------------------------------------------------------*/
    510 		if (rc==-1) {
    511 			NetStealth = stealth;
    512 			NetOpen = 0;
    513 			return(false);
    514 		} else {
    515 
    516 			/*---------------------------------------------------------------------
    517 			0 = user has joined an existing game; save values & return
    518 			---------------------------------------------------------------------*/
    519 			if (rc==0) {
    520 				Write_MultiPlayer_Settings ();
    521 				NetStealth = stealth;
    522 				NetOpen = 0;
    523 
    524 				return(true);
    525 			} else {
    526 
    527 				/*---------------------------------------------------------------------
    528 				1 = user requests New Network Game
    529 				---------------------------------------------------------------------*/
    530 				if (rc==1) {
    531 					/*..................................................................
    532 					Pop up the New Network Game dialog; if user selects OK, return
    533 					'true'; otherwise, return to the Join Dialog.
    534 					..................................................................*/
    535 					if (Net_New_Dialog()) {
    536 						Write_MultiPlayer_Settings ();
    537 						NetOpen = 0;
    538 						NetStealth = stealth;
    539 						NetOpen = 0;
    540 
    541 						return(true);
    542 					} else {
    543 						continue;
    544 					}
    545 				}
    546 			}
    547 		}
    548 	}
    549 }
    550 
    551 
    552 
    553 /***********************************************************************************************
    554  * Remote_Connect -- handles connecting this host to the server in an internet game 			    *
    555  *                                                                         						    *
    556  * INPUT:                                                                  						    *
    557  *		none.																												 *
    558  *                                                                         						    *
    559  * OUTPUT:                                                                 						    *
    560  *		true = connections established; false = not															 *
    561  *                                                                         						    *
    562  * WARNINGS:                                                               						    *
    563  *		none.																												 *
    564  *                                                                         						    *
    565  * HISTORY:                                                                						    *
    566  *   02/14/1995 BR : Created.                                              						    *
    567  *=============================================================================================*/
    568 bool Server_Remote_Connect(void)
    569 {
    570 	int stealth;				// original state of NetStealth flag
    571 
    572 	/*------------------------------------------------------------------------
    573 	Init network timing parameters; these values should work for both a "real"
    574 	network, and a simulated modem network (ie Kali)
    575 	------------------------------------------------------------------------*/
    576 	Ipx.Set_Timing (	30, 		// retry 2 times per second
    577 							-1, 		// ignore max retries
    578 							600);		// give up after 10 seconds
    579 
    580 	/*------------------------------------------------------------------------
    581 	Save the original value of the NetStealth flag, so we can turn stealth
    582 	off for now (during this portion of the dialogs, we must show ourselves)
    583 	------------------------------------------------------------------------*/
    584 	stealth = NetStealth;
    585 	NetStealth = 0;
    586 
    587 	/*------------------------------------------------------------------------
    588 	The game is now "open" for joining.  Close it as soon as we exit this
    589 	routine.
    590 	------------------------------------------------------------------------*/
    591 	NetOpen = 1;
    592 
    593 	/*------------------------------------------------------------------------
    594 	Read the default values from the INI file
    595 	------------------------------------------------------------------------*/
    596 	Read_MultiPlayer_Settings ();
    597 
    598 	if (!Net_Fake_New_Dialog()){
    599 		Write_MultiPlayer_Settings ();
    600 		return (false);
    601 	}
    602 
    603 	NetOpen = 0;
    604 	NetStealth = stealth;
    605 	Write_MultiPlayer_Settings ();
    606 	return (true);
    607 }
    608 
    609 
    610 /***********************************************************************************************
    611  * Client_Remote_Connect -- handles connecting this client to the server in an internet game   *
    612  *                                                                         						    *
    613  * INPUT:                                                                  						    *
    614  *		none.																												 *
    615  *                                                                         						    *
    616  * OUTPUT:                                                                 						    *
    617  *		true = connections established; false = not															 *
    618  *                                                                         						    *
    619  * WARNINGS:                                                               						    *
    620  *		none.																												 *
    621  *                                                                         						    *
    622  * HISTORY:                                                                						    *
    623  *   02/14/1995 ST : Created.                                              						    *
    624  *=============================================================================================*/
    625 bool Client_Remote_Connect(void)
    626 {
    627 	int rc;
    628 	int stealth;				// original state of NetStealth flag
    629 
    630 	/*------------------------------------------------------------------------
    631 	Init network timing parameters; these values should work for both a "real"
    632 	network, and a simulated modem network (ie Kali)
    633 	------------------------------------------------------------------------*/
    634 	Ipx.Set_Timing (	30, 		// retry 2 times per second
    635 							-1, 		// ignore max retries
    636 							600);		// give up after 10 seconds
    637 
    638 	/*------------------------------------------------------------------------
    639 	Save the original value of the NetStealth flag, so we can turn stealth
    640 	off for now (during this portion of the dialogs, we must show ourselves)
    641 	------------------------------------------------------------------------*/
    642 	stealth = NetStealth;
    643 	NetStealth = 0;
    644 
    645 	/*------------------------------------------------------------------------
    646 	The game is now "open" for joining.  Close it as soon as we exit this
    647 	routine.
    648 	------------------------------------------------------------------------*/
    649 	NetOpen = 1;
    650 
    651 	/*------------------------------------------------------------------------
    652 	Read the default values from the INI file
    653 	------------------------------------------------------------------------*/
    654 	Read_MultiPlayer_Settings ();
    655 
    656 	/*---------------------------------------------------------------------
    657 	Pop up the network Join/New dialog
    658 	---------------------------------------------------------------------*/
    659 	rc = Net_Fake_Join_Dialog();
    660 	Write_MultiPlayer_Settings ();
    661 
    662 	NetStealth = stealth;
    663 	NetOpen = 0;
    664 
    665 	if (rc == -1) {
    666 		return(false);
    667 	} else {
    668 		return(true);
    669 	}
    670 }
    671 
    672 
    673 
    674 /***********************************************************************************************
    675  * Net_Join_Dialog -- lets user join an existing game or start a new one							  *
    676  *                                                                         						  *
    677  * This dialog displays an edit field for the player's name, and a list of all non-stealth-	  *
    678  * mode games.  Clicking once on a game name displays a list of who's in that game.  Clicking  *
    679  * "New" takes the user to the Net_New dialog, where he waits for other users to join his		  *
    680  * game.  All other input is done through this dialog.													  *
    681  *                                                                         						  *
    682  * The dialog has several "states":																				  *
    683  *                                                                         						  *
    684  * 1) Initially, it waits for the user to fill in his/her name and then to select Join or New; *
    685  *    if New is selected, this dialog is exited.															  *
    686  *                                                                         						  *
    687  *	2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.  *
    688  *	   The join request is transmitted to the game's owner, and the message "Waiting for		  *
    689  *		Confirmation" is displayed, until a confirmation or denial is received from the game's	  *
    690  *		owner.  The user may click Cancel at this point to cancel the join request.				  *
    691  *		(Once Join is selected, the name editing field is disabled, and becomes a display-only	  *
    692  *		field.  If cancel is selected, it reappears as an edit field.) The user can still click  *
    693  *		around & see who's in which games.																		  *
    694  *                                                                         						  *
    695  *	3) If the join request is denied, the dialog re-initializes to its pre-join state; the		  *
    696  *		Join & New buttons reappear, & the Name field is available again.								  *
    697  *                                                                         						  *
    698  * 4) If join confirmation is obtained, the message just changes to "Confirmed.  Waiting for	  *
    699  *		Entry Signal." or some such nonsense.  The user can still click around & see who's		  *
    700  *		in which games.																								  *
    701  *                                                                         						  *
    702  * Any game running in Stealth mode won't show up on this dialog.										  *
    703  *                                                                         						  *
    704  *    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                     					  *
    705  *    ³                 Network Games                     ³                     					  *
    706  *    ³                                                   ³                     					  *
    707  *    ³              Your Name: ____________              ³                     					  *
    708  *    ³                  House: [GDI] [NOD]               ³                     					  *
    709  *    ³          Desired Color: [ ][ ][ ][ ]              ³                     					  *
    710  *    ³                                                   ³                     					  *
    711  *    ³            Games                 Players          ³                     					  *
    712  *    ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³                     					  *
    713  *    ³ ³(Bill's Game         )³³ ³ Peter Parker GDI ³³ ³                     					  *
    714  *    ³ ³ Peter Parker's Game  ÃÄ´ ³ Mary Jane    GDI ÃÄ´ ³                     					  *
    715  *    ³ ³(Magnum PI's Game    )³ ³ ³ JJ Jameson   NOD ³ ³ ³                     					  *
    716  *    ³ ³                      ÃÄ´ ³                  ÃÄ´ ³                     					  *
    717  *    ³ ³                      ³³ ³                  ³³ ³                     					  *
    718  *    ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³                     					  *
    719  *    ³           Scenario: Big Long Description          ³                     					  *
    720  *    ³                Starting Credits: xxxx             ³                     					  *
    721  *    ³          Count: ---          Level: ---           ³                     					  *
    722  *    ³          Bases: ON          Crates: ON            ³                          					  *
    723  *    ³       Tiberium: ON      AI Players: ON            ³                           					  *
    724  *    ³                                                   ³                     					  *
    725  *    ³            [Join]  [Cancel]    [New]              ³                     					  *
    726  *    ³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿  ³                     					  *
    727  *    ³  ³                                             ³  ³                     					  *
    728  *    ³  ³                                             ³  ³                     					  *
    729  *    ³  ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ  ³                     					  *
    730  *    ³                  [Send Message]                   ³                     					  *
    731  *    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ                     					  *
    732  *                                                                         						  *
    733  * INPUT:                                                                  						  *
    734  *		none.																												  *
    735  *                                                                         						  *
    736  * OUTPUT:                                                                 						  *
    737  *		-1 = cancel, 0 = OK, 1 = New net game requested														  *
    738  *                                                                         						  *
    739  * WARNINGS:                                                               						  *
    740  *		none.																												  *
    741  *                                                                         						  *
    742  * HISTORY:                                                                						  *
    743  *   02/14/1995 BR : Created.                                              						  *
    744  *=============================================================================================*/
    745 static int Net_Join_Dialog(void)
    746 {
    747 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
    748 	/*........................................................................
    749 	Dialog & button dimensions
    750 	........................................................................*/
    751 /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
    752 	int d_dialog_w = 287 *factor;											// dialog width
    753 	int d_dialog_h = 198*factor;											// dialog height
    754 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
    755 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
    756 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
    757 
    758 	int d_txt6_h = 6*factor+1;												// ht of 6-pt text
    759 	int d_margin1 = 5*factor;												// large margin
    760 	int d_margin2 = 2*factor;												// small margin
    761 
    762 	int d_name_w = 70*factor;
    763 	int d_name_h = 9*factor;
    764 	int d_name_x = d_dialog_cx - 10*factor;
    765 	int d_name_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h;
    766 
    767 	int d_gdi_w = 30*factor;
    768 	int d_gdi_h = 9*factor;
    769 	int d_gdi_x = d_dialog_cx - 10*factor;
    770 	int d_gdi_y = d_name_y + d_name_h + d_margin2;
    771 
    772 	int d_nod_w = 30*factor;
    773 	int d_nod_h = 9*factor;
    774 	int d_nod_x = d_gdi_x + d_gdi_w;
    775 	int d_nod_y = d_name_y + d_name_h + d_margin2;
    776 
    777 	int d_color_w = 10*factor;
    778 	int d_color_h = 9*factor;
    779 	int d_color_y = d_nod_y + d_nod_h + d_margin2;
    780 
    781 	int d_gamelist_w = 160*factor;
    782 	int d_gamelist_h = 27*factor;
    783 	int d_gamelist_x = d_dialog_x + d_margin1;
    784 	int d_gamelist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
    785 
    786 	int d_playerlist_w = 106*factor;
    787 	int d_playerlist_h = 27*factor;
    788 	int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_playerlist_w;
    789 	int d_playerlist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
    790 
    791 	int d_msg1_y = d_gamelist_y + d_gamelist_h + d_margin1;
    792 	int d_msg2_y = d_msg1_y + d_txt6_h;
    793 	int d_msg3_y = d_msg2_y + d_txt6_h;
    794 	int d_msg4_y = d_msg3_y + d_txt6_h;
    795 	int d_msg5_y = d_msg4_y + d_txt6_h;
    796 
    797 	int d_join_w = 40*factor;
    798 	int d_join_h = 9*factor;
    799 	int d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);
    800 	int d_join_y = d_msg5_y + d_txt6_h + d_margin1;
    801 
    802 #if (GERMAN | FRENCH)
    803 	int d_cancel_w = 50*factor;
    804 #else
    805 	int d_cancel_w = 40*factor;
    806 #endif
    807 	int d_cancel_h = 9*factor;
    808 	int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
    809 	int d_cancel_y = d_msg5_y + d_txt6_h + d_margin1;
    810 
    811 	int d_new_w = 40*factor;
    812 	int d_new_h = 9*factor;
    813 	int d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);
    814 	int d_new_y = d_msg5_y + d_txt6_h + d_margin1;
    815 
    816 	int d_message_w = d_dialog_w - (d_margin1 * 2);
    817 	int d_message_h = 34*factor;
    818 	int d_message_x = d_dialog_x + d_margin1;
    819 	int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
    820 
    821 	int d_send_w = 80*factor;
    822 	int d_send_h = 9*factor;
    823 	int d_send_x = d_dialog_cx - (d_send_w / 2);
    824 	int d_send_y = d_message_y + d_message_h + d_margin2;
    825 
    826 	/*........................................................................
    827 	Button Enumerations
    828 	........................................................................*/
    829 	enum {
    830 		BUTTON_NAME = 100,
    831 		BUTTON_GDI,
    832 		BUTTON_NOD,
    833 		BUTTON_GAMELIST,
    834 		BUTTON_PLAYERLIST,
    835 		BUTTON_JOIN,
    836 		BUTTON_CANCEL,
    837 		BUTTON_NEW,
    838 		BUTTON_SEND,
    839 	};
    840 
    841 	/*........................................................................
    842 	Redraw values: in order from "top" to "bottom" layer of the dialog
    843 	........................................................................*/
    844 	typedef enum {
    845 		REDRAW_NONE = 0,
    846 		REDRAW_MESSAGE,
    847 		REDRAW_COLORS,
    848 		REDRAW_BUTTONS,
    849 		REDRAW_BACKGROUND,
    850 		REDRAW_ALL = REDRAW_BACKGROUND
    851 	} RedrawType;
    852 
    853 	/*........................................................................
    854 	Dialog variables
    855 	........................................................................*/
    856 	RedrawType display = REDRAW_ALL;		// redraw level
    857 	bool process = true;						// process while true
    858 	KeyNumType input;
    859 	int cbox_x[] = {	d_gdi_x,
    860 							d_gdi_x + d_color_w,
    861 							d_gdi_x + (d_color_w * 2),
    862 							d_gdi_x + (d_color_w * 3),
    863 							d_gdi_x + (d_color_w * 4),
    864 							d_gdi_x + (d_color_w * 5)};
    865 
    866 	JoinStateType joinstate = JOIN_NOTHING;	// current "state" of this dialog
    867 	char namebuf[MPLAYER_NAME_MAX] = {0};		// buffer for player's name
    868 	int tabs[] = {77*factor};						// tabs for player list box
    869 	int game_index = -1;						// index of currently-selected game
    870 	int join_index = -1;						// index of game we're joining
    871 	int rc = 0;									// -1 = user cancelled, 1 = New
    872 	JoinEventType event;						// event from incoming packet
    873 	int i,j;										// loop counter
    874 	char txt[80];
    875 	char const *p;
    876 	int parms_received;						// 1 = game options received
    877 	int found;
    878 
    879 	unsigned char tmp_id[MAX_PLAYERS];	// temp storage for sorting player ID's
    880 	int min_index;								// for sorting player ID's
    881 	unsigned char min_id;					// for sorting player ID's
    882 	unsigned char id;							// connection ID
    883 	char * item;
    884 	unsigned long starttime;
    885 
    886 	NodeNameType *who;
    887 
    888 	int					message_length;
    889 	int					sent_so_far;
    890 	unsigned short		magic_number;
    891 	unsigned short		crc;
    892 
    893 	void const *up_button;
    894 	void const *down_button;
    895 
    896 	if (InMainLoop){
    897 		up_button = Hires_Retrieve("BTN-UP.SHP");
    898 		down_button = Hires_Retrieve("BTN-DN.SHP");
    899 	}else{
    900 		up_button = Hires_Retrieve("BTN-UP2.SHP");
    901 		down_button = Hires_Retrieve("BTN-DN2.SHP");
    902 	}
    903 
    904 
    905 	/*........................................................................
    906 	Buttons
    907 	........................................................................*/
    908 	GadgetClass *commands;										// button list
    909 
    910 	EditClass name_edt (BUTTON_NAME,
    911 		namebuf, MPLAYER_NAME_MAX, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    912 		d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
    913 
    914 	TextButtonClass gdibtn(BUTTON_GDI, TXT_G_D_I,
    915 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    916 		d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);
    917 
    918 	TextButtonClass nodbtn(BUTTON_NOD, TXT_N_O_D,
    919 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    920 		d_nod_x, d_nod_y, d_nod_w, d_nod_h);
    921 
    922 	ListClass gamelist(BUTTON_GAMELIST,
    923 		d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
    924 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    925 		up_button,
    926 		down_button);
    927 
    928 	ColorListClass playerlist(BUTTON_PLAYERLIST,
    929 		d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
    930 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    931 		up_button,
    932 		down_button);
    933 
    934 	TextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN,
    935 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    936 #ifdef FRENCH
    937 		d_join_x, d_join_y);
    938 #else
    939 		d_join_x, d_join_y, d_join_w, d_join_h);
    940 #endif
    941 
    942 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
    943 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    944 //#if (GERMAN | FRENCH)
    945 //		d_cancel_x, d_cancel_y);
    946 //#else
    947 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
    948 //#endif
    949 
    950 	TextButtonClass newbtn(BUTTON_NEW, TXT_NEW,
    951 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    952 		d_new_x, d_new_y, d_new_w, d_new_h);
    953 
    954 	TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
    955 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    956 //#if (GERMAN | FRENCH)
    957 //		d_send_x, d_send_y);
    958 //#else
    959 		d_send_x, d_send_y, d_send_w, d_send_h);
    960 //#endif
    961 
    962 	playerlist.Set_Tabs(tabs);
    963 
    964 	/*
    965 	----------------------------- Various Inits ------------------------------
    966 	*/
    967 	MPlayerColorIdx = MPlayerPrefColor;			// init my preferred color
    968 	strcpy (namebuf, MPlayerName);				// set my name
    969 	name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
    970 	name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
    971 
    972 	playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
    973 
    974 	if (MPlayerHouse==HOUSE_GOOD) {
    975 		gdibtn.Turn_On();
    976 	} else {
    977 		nodbtn.Turn_On();
    978 	}
    979 
    980 	Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
    981 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
    982 
    983 	Messages.Init (d_message_x + 2, d_message_y + 2, 4,
    984 		MAX_MESSAGE_LENGTH, d_txt6_h);
    985 
    986 	/*
    987 	--------------------------- Send network query ---------------------------
    988 	*/
    989 	Send_Join_Queries (game_index, 1, 0);
    990 
    991 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
    992 	Blit_Hid_Page_To_Seen_Buff();
    993 	Set_Palette(Palette);
    994 
    995 	/*
    996 	---------------------------- Init Mono Output ----------------------------
    997 	*/
    998 	#if(SHOW_MONO)
    999 	Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType),
   1000 		sizeof(NetCommandType), GlobalPacketNames, 11);
   1001 	Ipx.Mono_Debug_Print(-1,1);
   1002 	#endif
   1003 	while (Get_Mouse_State() > 0) Show_Mouse();
   1004 
   1005 	/*
   1006 	---------------------------- Processing loop -----------------------------
   1007 	*/
   1008 	while (process) {
   1009 
   1010 		/*
   1011 		** If we have just received input focus again after running in the background then
   1012 		** we need to redraw.
   1013 		*/
   1014 		if (AllSurfaces.SurfacesRestored){
   1015 			AllSurfaces.SurfacesRestored=FALSE;
   1016 			display=REDRAW_ALL;
   1017 		}
   1018 
   1019 		#if(SHOW_MONO)
   1020 		Ipx.Mono_Debug_Print(-1,0);
   1021 		#endif
   1022 		/*
   1023 		...................... Refresh display if needed ......................
   1024 		*/
   1025 		if (display) {
   1026 			Hide_Mouse();
   1027 			/*
   1028 			.................. Redraw backgound & dialog box ...................
   1029 			*/
   1030 			if (display >= REDRAW_BACKGROUND) {
   1031 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   1032 				Blit_Hid_Page_To_Seen_Buff();
   1033 				Set_Palette(Palette);
   1034 
   1035 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
   1036 
   1037 				/*...............................................................
   1038 				Dialog & Field labels
   1039 				...............................................................*/
   1040 				Draw_Caption (TXT_JOIN_NETWORK_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
   1041 
   1042 				Fancy_Text_Print(TXT_YOUR_NAME,
   1043 					d_name_x - 5, d_name_y + 1, CC_GREEN, TBLACK,
   1044 					TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1045 
   1046 				Fancy_Text_Print(TXT_SIDE_COLON,
   1047 					d_gdi_x - 5, d_gdi_y + 1, CC_GREEN, TBLACK,
   1048 					TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1049 
   1050 				Fancy_Text_Print(TXT_COLOR_COLON,
   1051 					cbox_x[0] - 5, d_color_y + 1, CC_GREEN, TBLACK,
   1052 					TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1053 
   1054 				Fancy_Text_Print(TXT_GAMES,
   1055 					d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h,
   1056 					CC_GREEN, TBLACK,
   1057 					TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1058 
   1059 				Fancy_Text_Print(TXT_PLAYERS,
   1060 					d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
   1061 					CC_GREEN, TBLACK,
   1062 					TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1063 
   1064 				/*...............................................................
   1065 				Join-state-specific labels:
   1066 				...............................................................*/
   1067 				if (joinstate > JOIN_NOTHING) {
   1068 					Fancy_Text_Print(namebuf, d_name_x, d_name_y + 1, CC_GREEN,
   1069 						TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1070 					if (MPlayerHouse==HOUSE_GOOD) {
   1071 						Fancy_Text_Print(TXT_G_D_I, d_gdi_x, d_gdi_y + 1, CC_GREEN,
   1072 							TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1073 					} else {
   1074 						Fancy_Text_Print(TXT_N_O_D, d_gdi_x, d_gdi_y + 1, CC_GREEN,
   1075 							TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1076 					}
   1077 				}
   1078 
   1079 				/*
   1080 				.................... Rebuild the button list ....................
   1081 				*/
   1082 				cancelbtn.Zap();
   1083 				gamelist.Zap();
   1084 				playerlist.Zap();
   1085 				gdibtn.Zap();
   1086 				nodbtn.Zap();
   1087 				name_edt.Zap();
   1088 				joinbtn.Zap();
   1089 				newbtn.Zap();
   1090 				sendbtn.Zap();
   1091 
   1092 				commands = &cancelbtn;
   1093 				gamelist.Add_Tail(*commands);
   1094 				playerlist.Add_Tail(*commands);
   1095 				/*...............................................................
   1096 				Only add the name edit field, the House, Join & New buttons if
   1097 				we're doing nothing, or we've just been rejected.
   1098 				...............................................................*/
   1099 				if (joinstate <= JOIN_NOTHING) {
   1100 					gdibtn.Add_Tail(*commands);
   1101 					nodbtn.Add_Tail(*commands);
   1102 					name_edt.Add_Tail(*commands);
   1103 					joinbtn.Add_Tail(*commands);
   1104 					newbtn.Add_Tail(*commands);
   1105 				}
   1106 				if (joinstate == JOIN_CONFIRMED)
   1107 					sendbtn.Add_Tail(*commands);
   1108 			}
   1109 			/*
   1110 			.......................... Redraw buttons ..........................
   1111 			*/
   1112 			if (display >= REDRAW_BUTTONS) {
   1113 				commands->Draw_All();
   1114 			}
   1115 
   1116 			/*..................................................................
   1117 			Draw the color boxes
   1118 			..................................................................*/
   1119 			if (display >= REDRAW_COLORS) {
   1120 				for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
   1121 					LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,
   1122 						cbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2,
   1123 						MPlayerGColors[i]);
   1124 
   1125 					if (i == MPlayerColorIdx) {
   1126 						Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
   1127 							BOXSTYLE_GREEN_DOWN, false);
   1128 					} else {
   1129 						Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
   1130 							BOXSTYLE_GREEN_RAISED, false);
   1131 					}
   1132 				}
   1133 			}
   1134 
   1135 			/*..................................................................
   1136 			Draw the message:
   1137 			- Erase an old message first
   1138 			- If we're in a game, print the game options (if they've been
   1139 			  received)
   1140 			- If we've been rejected from a game, print that message
   1141 			..................................................................*/
   1142 			if (display >= REDRAW_MESSAGE) {
   1143 				Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
   1144 					BOXSTYLE_GREEN_BORDER, true);
   1145 				Messages.Draw();
   1146 
   1147 				LogicPage->Fill_Rect( d_dialog_x + 2,
   1148 					d_msg1_y,
   1149 					d_dialog_x + d_dialog_w - 4,
   1150 					d_msg5_y + d_txt6_h,
   1151 					BLACK);
   1152 
   1153 				if (joinstate==JOIN_CONFIRMED && parms_received) {
   1154 					/*............................................................
   1155 					Scenario title
   1156 					............................................................*/
   1157 					p = Text_String(TXT_SCENARIO_COLON);
   1158 					if (ScenarioIdx != -1) {
   1159 						sprintf(txt,"%s %s",p, MPlayerScenarios[ScenarioIdx]);
   1160 
   1161 						Fancy_Text_Print (txt, d_dialog_cx,
   1162 							d_msg1_y, CC_GREEN, TBLACK,
   1163 							TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
   1164 					} else {
   1165 						sprintf(txt,"%s %s",p,Text_String(TXT_NOT_FOUND));
   1166 
   1167 						Fancy_Text_Print (txt, d_dialog_cx,
   1168 							d_msg1_y, CC_NOD_COLOR, TBLACK,
   1169 							TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
   1170 					}
   1171 
   1172 					/*............................................................
   1173 					# of credits
   1174 					............................................................*/
   1175 					p = Text_String(TXT_START_CREDITS_COLON);
   1176 					sprintf(txt, "%s %d", p, MPlayerCredits);
   1177 					Fancy_Text_Print (txt, d_dialog_cx,
   1178 						d_msg2_y, CC_GREEN, TBLACK,
   1179 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
   1180 
   1181 					/*............................................................
   1182 					Count & Level values
   1183 					............................................................*/
   1184 					p = Text_String(TXT_COUNT);
   1185 					sprintf(txt,"%s %d",p,MPlayerUnitCount);
   1186 					Fancy_Text_Print (txt,
   1187 						d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
   1188 						d_msg3_y, CC_GREEN, TBLACK,
   1189 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1190 
   1191 					p = Text_String(TXT_LEVEL);
   1192 					if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
   1193 						sprintf(txt, "%s %d", p, BuildLevel);
   1194 					} else {
   1195 						sprintf(txt, "%s **", p);
   1196 					}
   1197 					Fancy_Text_Print (txt,
   1198 						d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
   1199 						d_msg3_y, CC_GREEN, TBLACK,
   1200 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1201 
   1202 					/*............................................................
   1203 					Bases
   1204 					............................................................*/
   1205 					p = Text_String(TXT_BASES_COLON);
   1206 					if (MPlayerBases) {
   1207 						sprintf(txt,"%s %s",p,Text_String(TXT_ON));
   1208 					} else {
   1209 						sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
   1210 					}
   1211 					Fancy_Text_Print (txt,
   1212 						d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
   1213 						d_msg4_y, CC_GREEN, TBLACK,
   1214 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1215 
   1216 					/*............................................................
   1217 					Tiberium
   1218 					............................................................*/
   1219 					p = Text_String(TXT_TIBERIUM_COLON);
   1220 					if (MPlayerTiberium) {
   1221 						sprintf(txt,"%s %s",p,Text_String(TXT_ON));
   1222 					} else {
   1223 						sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
   1224 					}
   1225 
   1226 					Fancy_Text_Print (txt,
   1227 						d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
   1228 						d_msg5_y, CC_GREEN, TBLACK,
   1229 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1230 
   1231 					/*............................................................
   1232 					Goody boxes
   1233 					............................................................*/
   1234 					p = Text_String(TXT_CRATES_COLON);
   1235 					if (MPlayerGoodies) {
   1236 						sprintf(txt,"%s %s",p,Text_String(TXT_ON));
   1237 					} else {
   1238 						sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
   1239 					}
   1240 
   1241 					Fancy_Text_Print (txt,
   1242 						d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
   1243 						d_msg4_y, CC_GREEN, TBLACK,
   1244 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1245 
   1246 					/*............................................................
   1247 					Computer AI players
   1248 					............................................................*/
   1249 					if (Special.IsCaptureTheFlag) {
   1250 						p = Text_String(TXT_CAPTURE_THE_FLAG_COLON);
   1251 						sprintf(txt,"%s %s",p,Text_String(TXT_ON));
   1252 					} else {
   1253 						p = Text_String(TXT_AI_PLAYERS_COLON);
   1254 						if (MPlayerGhosts) {
   1255 							sprintf(txt,"%s %s",p,Text_String(TXT_ON));
   1256 						} else {
   1257 							sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
   1258 						}
   1259 					}
   1260 					Fancy_Text_Print (txt,
   1261 						d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
   1262 						d_msg5_y, CC_GREEN, TBLACK,
   1263 						TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1264 
   1265 				} else {
   1266 
   1267 					/*...............................................................
   1268 					Rejection notice
   1269 					...............................................................*/
   1270 					if (joinstate==JOIN_REJECTED) {
   1271 						Fancy_Text_Print(TXT_REQUEST_DENIED,
   1272 							d_dialog_cx, d_msg3_y, CC_GREEN, TBLACK,
   1273 							TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   1274 					}
   1275 				}
   1276 			}
   1277 
   1278 			Show_Mouse();
   1279 			display = REDRAW_NONE;
   1280 		}
   1281 
   1282 		/*
   1283 		........................... Get user input ............................
   1284 		*/
   1285 		input = commands->Input();
   1286 
   1287 		/*
   1288 		---------------------------- Process input ----------------------------
   1289 		*/
   1290 		switch (input) {
   1291 			/*------------------------------------------------------------------
   1292 			User clicks on a color button:
   1293 			- If we've joined a game, don't allow a new color selection
   1294 			- otherwise, select that color
   1295 			------------------------------------------------------------------*/
   1296 			case KN_LMOUSE:
   1297 				if (joinstate > JOIN_NOTHING)
   1298 					break;
   1299 				if (_Kbd->MouseQX > cbox_x[0] &&
   1300 					_Kbd->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
   1301 					_Kbd->MouseQY > d_color_y &&
   1302 					_Kbd->MouseQY < (d_color_y + d_color_h)) {
   1303 						MPlayerPrefColor = (_Kbd->MouseQX - cbox_x[0]) / d_color_w;
   1304 						MPlayerColorIdx = MPlayerPrefColor;
   1305 
   1306 						name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
   1307 						name_edt.Flag_To_Redraw();
   1308 
   1309 						display = REDRAW_COLORS;
   1310 				}
   1311 				break;
   1312 
   1313 			/*------------------------------------------------------------------
   1314 			User clicks on the game list:
   1315 			- If we've joined a game, don't allow the selected item to change;
   1316 			otherwise:
   1317 			- Clear the player list
   1318 			- Send an immediate player query
   1319 			------------------------------------------------------------------*/
   1320 			case (BUTTON_GAMELIST | KN_BUTTON):
   1321 				if (joinstate==JOIN_CONFIRMED) {
   1322 					gamelist.Set_Selected_Index(game_index);
   1323 				} else {
   1324 					if (gamelist.Current_Index() != game_index) {
   1325 						Clear_Player_List (&playerlist);
   1326 						game_index = gamelist.Current_Index();
   1327 						Send_Join_Queries (game_index, 0, 1);
   1328 					}
   1329 				}
   1330 				break;
   1331 
   1332 			/*------------------------------------------------------------------
   1333 			House Buttons: set the player's desired House
   1334 			------------------------------------------------------------------*/
   1335 			case (BUTTON_GDI | KN_BUTTON):
   1336 				MPlayerHouse = HOUSE_GOOD;
   1337 				gdibtn.Turn_On();
   1338 				nodbtn.Turn_Off();
   1339 				break;
   1340 
   1341 			case (BUTTON_NOD | KN_BUTTON):
   1342 				MPlayerHouse = HOUSE_BAD;
   1343 				gdibtn.Turn_Off();
   1344 				nodbtn.Turn_On();
   1345 				break;
   1346 
   1347 			/*------------------------------------------------------------------
   1348 			JOIN: send a join request packet & switch to waiting-for-confirmation
   1349 			mode.  (Request_To_Join fills in MPlayerName with my namebuf.)
   1350 			------------------------------------------------------------------*/
   1351 			case (BUTTON_JOIN | KN_BUTTON):
   1352 				name_edt.Clear_Focus();
   1353 				name_edt.Flag_To_Redraw();
   1354 
   1355 				join_index = gamelist.Current_Index();
   1356 				parms_received = 0;
   1357 				if (Request_To_Join (namebuf, join_index, &playerlist, MPlayerHouse,
   1358 					MPlayerColorIdx)) {
   1359 					joinstate = JOIN_WAIT_CONFIRM;
   1360 				} else {
   1361 					display = REDRAW_ALL;
   1362 				}
   1363 				break;
   1364 
   1365 			/*------------------------------------------------------------------
   1366 			CANCEL: send a SIGN_OFF
   1367 			- If we're part of a game, stay in this dialog; otherwise, exit
   1368 			------------------------------------------------------------------*/
   1369 			case (KN_ESC):
   1370 				if (Messages.Get_Edit_Buf() != NULL) {
   1371 					Messages.Input(input);
   1372 					display = REDRAW_MESSAGE;
   1373 					break;
   1374 				}
   1375 			case (BUTTON_CANCEL | KN_BUTTON):
   1376 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   1377 
   1378 				GPacket.Command = NET_SIGN_OFF;
   1379 				strcpy(GPacket.Name,MPlayerName);
   1380 
   1381 				/*...............................................................
   1382 				If we're joined to a game, make extra sure the other players in
   1383 				that game know I'm exiting; send my SIGN_OFF as an ack-required
   1384 				packet.  Do not send this packet to myself (index 0).
   1385 				...............................................................*/
   1386 				if (joinstate == JOIN_CONFIRMED) {
   1387 					//
   1388 					// Remove myself from the player list box
   1389 					//
   1390 					if (playerlist.Count()) { 	// added: BRR 6/14/96
   1391 						item = (char *)(playerlist.Get_Item(0));
   1392 						playerlist.Remove_Item(item);
   1393 						delete [] item;
   1394 						playerlist.Flag_To_Redraw();
   1395 					}
   1396 
   1397 					//
   1398 					// Remove myself from the Players list
   1399 					//
   1400 					if (Players.Count()) {		// added: BRR 6/14/96
   1401 						who = Players[0];
   1402 						Players.Delete(0);
   1403 						delete who;
   1404 					}
   1405 
   1406 					for (i = 0; i < Players.Count(); i++) {
   1407 						Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   1408 							&(Players[i]->Address));
   1409 						Ipx.Service();
   1410 					}
   1411 				}
   1412 
   1413 				/*...............................................................
   1414 				Now broadcast my SIGN_OFF so other players looking at this game
   1415 				know I'm leaving.
   1416 				...............................................................*/
   1417 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   1418 					0, NULL);
   1419 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   1420 					0, NULL);
   1421 
   1422 				if (IsBridge) {
   1423 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   1424 						&BridgeNet);
   1425 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   1426 						&BridgeNet);
   1427 				}
   1428 
   1429 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   1430 
   1431 				if (joinstate != JOIN_CONFIRMED) {
   1432 					process = false;
   1433 					rc = -1;
   1434 				} else {
   1435 					MPlayerGameName[0] = 0;
   1436 					joinstate = JOIN_NOTHING;
   1437 					display = REDRAW_ALL;
   1438 				}
   1439 				break;
   1440 
   1441 			/*------------------------------------------------------------------
   1442 			NEW: bail out with return code 1
   1443 			------------------------------------------------------------------*/
   1444 			case (BUTTON_NEW | KN_BUTTON):
   1445 				/*
   1446 				.................. Force user to enter a name ...................
   1447 				*/
   1448 				if (strlen(namebuf)==0) {
   1449 					CCMessageBox().Process(TXT_NAME_ERROR);
   1450 					display = REDRAW_ALL;
   1451 					break;
   1452 				}
   1453 				/*
   1454 				..................... Ensure name is unique .....................
   1455 				*/
   1456 				found = 0;
   1457 				for (i = 0; i < Games.Count(); i++) {
   1458 					if (!stricmp(Games[i]->Name, namebuf)) {
   1459 						found = 1;
   1460 						CCMessageBox().Process (TXT_GAMENAME_MUSTBE_UNIQUE);
   1461 						display = REDRAW_ALL;
   1462 						break;
   1463 					}
   1464 				}
   1465 				if (found)
   1466 					break;
   1467 				/*
   1468 				.................... Save player & game name ....................
   1469 				*/
   1470 				strcpy(MPlayerName,namebuf);
   1471 				strcpy(MPlayerGameName,namebuf);
   1472 
   1473 				name_edt.Clear_Focus();
   1474 				name_edt.Flag_To_Redraw();
   1475 
   1476 				rc = 1;
   1477 				process = false;
   1478 				break;
   1479 
   1480 			/*------------------------------------------------------------------
   1481 			Default: manage the inter-player messages
   1482 			------------------------------------------------------------------*/
   1483 			default:
   1484 				/*...............................................................
   1485 				F4/SEND/'M' = edit a message
   1486 				...............................................................*/
   1487 				if (Messages.Get_Edit_Buf()==NULL) {
   1488 					if ( (input == KN_M && joinstate==JOIN_CONFIRMED) ||
   1489 						input==(BUTTON_SEND | KN_BUTTON) || input == KN_F4) {
   1490 						memset (txt, 0, 80);
   1491 
   1492 						strcpy(txt,Text_String(TXT_TO_ALL));	// "To All:"
   1493 
   1494 						Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
   1495 							TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
   1496 
   1497 						if (joinstate <= JOIN_NOTHING) {
   1498 							name_edt.Clear_Focus();
   1499 							name_edt.Flag_To_Redraw();
   1500 						}
   1501 
   1502 						display = REDRAW_MESSAGE;
   1503 
   1504 						break;
   1505 					}
   1506 				} else
   1507 
   1508 				/*...............................................................
   1509 				If we're already editing a message and the user clicks on
   1510 				'Send', translate our input to a Return so Messages.Input() will
   1511 				work properly.
   1512 				...............................................................*/
   1513 				if (input==(BUTTON_SEND | KN_BUTTON)) {
   1514 					input = KN_RETURN;
   1515 				}
   1516 
   1517 				/*...............................................................
   1518 				Manage the message system (get rid of old messages)
   1519 				...............................................................*/
   1520 				if (Messages.Manage()) {
   1521 					display = REDRAW_MESSAGE;
   1522 				}
   1523 
   1524 				/*...............................................................
   1525 				Service keyboard input for any message being edited.
   1526 				...............................................................*/
   1527 				i = Messages.Input(input);
   1528 
   1529 				/*...............................................................
   1530 				If 'Input' returned 1, it means refresh the message display.
   1531 				...............................................................*/
   1532 				if (i==1) {
   1533 					Messages.Draw();
   1534 				} else {
   1535 
   1536 					/*...............................................................
   1537 					If 'Input' returned 2, it means redraw the message display.
   1538 					...............................................................*/
   1539 					if (i==2) {
   1540 						display = REDRAW_MESSAGE;
   1541 					} else {
   1542 
   1543 						/*...............................................................
   1544 						If 'input' returned 3, it means send the current message.
   1545 						...............................................................*/
   1546 						if (i==3) {
   1547 							long actual_message_size;
   1548 							char *the_string;
   1549 
   1550 							sent_so_far = 0;
   1551  							magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
   1552 							message_length = strlen(Messages.Get_Edit_Buf());
   1553 							crc = (unsigned short)
   1554 									(Calculate_CRC(Messages.Get_Edit_Buf(),message_length) &0xffff);
   1555 
   1556 							while ( sent_so_far < message_length ){
   1557 								GPacket.Command = NET_MESSAGE;
   1558 								strcpy (GPacket.Name, namebuf);
   1559 								memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
   1560 
   1561 								/*
   1562 								** Steve I's stuff for splitting message on word boundries
   1563 								*/
   1564 								actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
   1565 
   1566 								/* Start at the end of the message and find a space with 10 chars. */
   1567 								the_string = GPacket.Message.Buf;
   1568 								while ( (COMPAT_MESSAGE_LENGTH -5) -actual_message_size < 10 &&
   1569 									the_string[actual_message_size] != ' '){
   1570 									--actual_message_size;
   1571 								}
   1572 								if ( the_string[actual_message_size] == ' ' ){
   1573 
   1574 									/* Now delete the extra characters after the space (they musnt print) */
   1575 									for ( int i=0 ; i< (COMPAT_MESSAGE_LENGTH-5) - actual_message_size; i++ ){
   1576 										the_string[i + actual_message_size] = 0;	//0xff; ST - 12/18/2018 11:36AM
   1577 									}
   1578 								}else{
   1579 									actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
   1580 								}
   1581 
   1582 
   1583 								*(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
   1584 								*((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
   1585 								*((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
   1586 								GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   1587 								GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
   1588 
   1589 								/*..................................................................
   1590 								Send the message to every player in our player list.  The local
   1591 								system will also receive this message, since it's in the Player list.
   1592 								..................................................................*/
   1593 								if (joinstate == JOIN_CONFIRMED) {
   1594 									for (i = 1; i < Players.Count(); i++) {
   1595 										Ipx.Send_Global_Message (&GPacket,
   1596 											sizeof(GlobalPacketType), 1, &(Players[i]->Address));
   1597 										Ipx.Service();
   1598 									}
   1599 
   1600 									sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
   1601 									Messages.Add_Message (txt,
   1602 										MPlayerTColors[MPlayerColorIdx],
   1603 										TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, magic_number, crc);
   1604 								}
   1605 								else {
   1606 									for (i = 0; i < Players.Count(); i++) {
   1607 										Ipx.Send_Global_Message (&GPacket,
   1608 											sizeof(GlobalPacketType), 1, &(Players[i]->Address));
   1609 										Ipx.Service();
   1610 									}
   1611 								}
   1612 								magic_number++;
   1613 								sent_so_far += actual_message_size;	//COMPAT_MESSAGE_LENGTH-5;
   1614 							}
   1615 						}
   1616 					}
   1617 				}
   1618 				break;
   1619 		}
   1620 
   1621 		/*---------------------------------------------------------------------
   1622 		Resend our query packets
   1623 		---------------------------------------------------------------------*/
   1624 		Send_Join_Queries(game_index, 0, 0);
   1625 
   1626 		/*---------------------------------------------------------------------
   1627 		Process incoming packets
   1628 		---------------------------------------------------------------------*/
   1629 		event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
   1630 			join_index);
   1631 		/*.....................................................................
   1632 		If we've changed state, redraw everything; if we're starting the game,
   1633 		break out of the loop.  If we've just joined, send out a player query
   1634 		so I'll get added to the list instantly.
   1635 		.....................................................................*/
   1636 		if (event == EV_STATE_CHANGE) {
   1637 			display = REDRAW_ALL;
   1638 			if (joinstate==JOIN_GAME_START) {
   1639 				rc = 0;
   1640 				process = false;
   1641 			} else {
   1642 
   1643 				/*..................................................................
   1644 				If we're newly-confirmed, immediately send out a player query
   1645 				..................................................................*/
   1646 				if (joinstate==JOIN_CONFIRMED) {
   1647 
   1648 					Clear_Player_List(&playerlist);
   1649 
   1650 					item = new char [MPLAYER_NAME_MAX + 4];
   1651 					if (MPlayerHouse==HOUSE_GOOD) {
   1652 						sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
   1653 					} else {
   1654 						sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
   1655 					}
   1656 					playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
   1657 
   1658 					who = new NodeNameType;
   1659 					strcpy(who->Name, MPlayerName);
   1660 					who->Address = IPXAddressClass();
   1661 					who->Player.House = MPlayerHouse;
   1662 					who->Player.Color = MPlayerColorIdx;
   1663 					Players.Add (who);
   1664 
   1665 					Send_Join_Queries (game_index, 0, 1);
   1666 				} else {
   1667 
   1668 					/*..................................................................
   1669 					If we've been rejected, clear any messages we may have been typing.
   1670 					..................................................................*/
   1671 					if (joinstate==JOIN_REJECTED) {
   1672 
   1673 						//
   1674 						// Remove myself from the player list box
   1675 						//
   1676 						if (playerlist.Count()) { 	// added: BRR 6/14/96
   1677 							item = (char *)(playerlist.Get_Item(0));
   1678 							if (item){
   1679 								playerlist.Remove_Item(item);
   1680 								delete [] item;
   1681 								playerlist.Flag_To_Redraw();
   1682 							}
   1683 						}
   1684 
   1685 						//
   1686 						// Remove myself from the Players list
   1687 						//
   1688 						if (Players.Count()){
   1689 							who = Players[0];
   1690 							Players.Delete(0);
   1691 							delete who;
   1692 						}
   1693 
   1694 						Messages.Init (d_message_x + 2, d_message_y + 2, 4,
   1695 							MAX_MESSAGE_LENGTH, d_txt6_h);
   1696 					}
   1697 				}
   1698 			}
   1699 		} else
   1700 
   1701 		/*.....................................................................
   1702 		If a new game is detected, and it's the first game on our list,
   1703 		automatically send out a player query for that game.
   1704 		.....................................................................*/
   1705 		if (event == EV_NEW_GAME && gamelist.Count()==1) {
   1706 			gamelist.Set_Selected_Index(0);
   1707 			game_index = gamelist.Current_Index();
   1708 			Send_Join_Queries (game_index, 0, 1);
   1709 		} else
   1710 
   1711 		/*.....................................................................
   1712 		If the game options have changed, print them.
   1713 		.....................................................................*/
   1714 		if (event == EV_GAME_OPTIONS) {
   1715 			parms_received = 1;
   1716 			display = REDRAW_MESSAGE;
   1717 		} else
   1718 
   1719 		/*.....................................................................
   1720 		Draw an incoming message
   1721 		.....................................................................*/
   1722 		if (event == EV_MESSAGE) {
   1723 			display = REDRAW_MESSAGE;
   1724 		} else
   1725 
   1726 		/*.....................................................................
   1727 		A game before the one I've selected is gone, so we have a new index now.
   1728 		'game_index' must be kept set to the currently-selected list item, so
   1729 		we send out queries for the currently-selected game.  It's therefore
   1730 		imperative that we detect any changes to the game list.
   1731 		If we're joined in a game, we must decrement our game_index to keep
   1732 		it aligned with the game we're joined to.
   1733 		.....................................................................*/
   1734 		if (event == EV_GAME_SIGNOFF) {
   1735 			if (joinstate==JOIN_CONFIRMED) {
   1736 				game_index--;
   1737 				join_index--;
   1738 				gamelist.Set_Selected_Index(join_index);
   1739 			} else {
   1740 				gamelist.Flag_To_Redraw();
   1741 				Clear_Player_List(&playerlist);
   1742 				game_index = gamelist.Current_Index();
   1743 				Send_Join_Queries (game_index, 0, 1);
   1744 			}
   1745 		}
   1746 
   1747 		/*---------------------------------------------------------------------
   1748 		Service the Ipx connections
   1749 		---------------------------------------------------------------------*/
   1750 		Ipx.Service();
   1751 
   1752 		/*---------------------------------------------------------------------
   1753 		Clean out the Game List; if an old entry is found:
   1754 		- Remove it
   1755 		- Clear the player list
   1756 		- Send queries for the new selected game, if there is one
   1757 		---------------------------------------------------------------------*/
   1758 		for (i = 0; i < Games.Count(); i++) {
   1759 			if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
   1760 				Games.Delete(Games[i]);
   1761 				item = (char *)(gamelist.Get_Item (i));
   1762 				gamelist.Remove_Item (item);
   1763 				delete [] item;
   1764 				if (i <= game_index) {
   1765 					gamelist.Flag_To_Redraw();
   1766 					Clear_Player_List(&playerlist);
   1767 					game_index = gamelist.Current_Index();
   1768 					Send_Join_Queries (game_index, 0, 1);
   1769 				}
   1770 			}
   1771 		}
   1772 
   1773 		/*---------------------------------------------------------------------
   1774 		Service the sounds & score; GameActive must be false at this point,
   1775 		so Call_Back() doesn't intercept global messages from me!
   1776 		---------------------------------------------------------------------*/
   1777 		Call_Back();
   1778 	}
   1779 
   1780 	/*------------------------------------------------------------------------
   1781 	Establish connections with all other players.
   1782 	------------------------------------------------------------------------*/
   1783 	if (rc == 0) {
   1784 		/*.....................................................................
   1785 		If the other guys are playing a scenario I don't have (sniff), I can't
   1786 		play.  Try to bail gracefully.
   1787 		.....................................................................*/
   1788 		if (ScenarioIdx==-1) {
   1789 			CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
   1790 
   1791 			//
   1792 			// Remove myself from the player list box
   1793 			//
   1794 			if (playerlist.Count()) { 	// added: BRR 6/14/96
   1795 				item = (char *)(playerlist.Get_Item(0));
   1796 				playerlist.Remove_Item(item);
   1797 				delete [] item;
   1798 				playerlist.Flag_To_Redraw();
   1799 			}
   1800 
   1801 			//
   1802 			// Remove myself from the Players list
   1803 			//
   1804 			if (Players.Count()) {		// added: BRR 6/14/96
   1805 				who = Players[0];
   1806 				Players.Delete(0);
   1807 				delete who;
   1808 			}
   1809 
   1810 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   1811 
   1812 			GPacket.Command = NET_SIGN_OFF;
   1813 			strcpy (GPacket.Name, MPlayerName);
   1814 
   1815 			for (i = 0; i < Players.Count(); i++) {
   1816 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   1817 					&(Players[i]->Address));
   1818 				Ipx.Service();
   1819 			}
   1820 
   1821 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   1822 				0, NULL);
   1823 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   1824 				0, NULL);
   1825 
   1826 			if (IsBridge) {
   1827 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   1828 					&BridgeNet);
   1829 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   1830 					&BridgeNet);
   1831 			}
   1832 
   1833 			while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   1834 
   1835 			rc = -1;
   1836 
   1837 		} else {
   1838 
   1839 			/*..................................................................
   1840 			Set the number of players in this game, and my ID
   1841 			..................................................................*/
   1842 			MPlayerCount = Players.Count();
   1843 			MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   1844 
   1845 			/*..................................................................
   1846 			Get the scenario number
   1847 			..................................................................*/
   1848 			Scenario = MPlayerFilenum[ScenarioIdx];
   1849 
   1850 			/*..................................................................
   1851 			Form connections with all other players.  Form the IPX Connection ID
   1852 			from the player's Color and House.  This will let us extract any
   1853 			player's color & house at any time.  Fill in 'tmp_id' while we're
   1854 			doing this.
   1855 			..................................................................*/
   1856 			for (i = 0; i < Players.Count(); i++) {
   1857 
   1858 				/*...............................................................
   1859 				Only create the connection if it's not myself!
   1860 				...............................................................*/
   1861 				if (strcmp (MPlayerName, Players[i]->Name)) {
   1862 					id = Build_MPlayerID(Players[i]->Player.Color,
   1863 						Players[i]->Player.House);
   1864 
   1865 					tmp_id[i] = id;
   1866 
   1867 					Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
   1868 				} else {
   1869 					tmp_id[i] = MPlayerLocalID;
   1870 				}
   1871 			}
   1872 
   1873 			/*..................................................................
   1874 			Store every player's ID in the MPlayerID[] array.  This array will
   1875 			determine the order of event execution, so the ID's must be stored
   1876 			in the same order on all systems.
   1877 			..................................................................*/
   1878 			for (i = 0; i < MPlayerCount; i++) {
   1879 				min_index = 0;
   1880 				min_id = 0xff;
   1881 				for (j = 0; j < MPlayerCount; j++) {
   1882 					if (tmp_id[j] < min_id) {
   1883 						min_id = tmp_id[j];
   1884 						min_index = j;
   1885 					}
   1886 				}
   1887 				MPlayerID[i] = tmp_id[min_index];
   1888 				tmp_id[min_index] = 0xff;
   1889 			}
   1890 			/*..................................................................
   1891 			Fill in the array of player names, including my own.
   1892 			..................................................................*/
   1893 			for (i = 0; i < MPlayerCount; i++) {
   1894 				if (MPlayerID[i] == MPlayerLocalID) {
   1895 					strcpy (MPlayerNames[i], MPlayerName);
   1896 				} else {
   1897 					strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
   1898 				}
   1899 			}
   1900 		}
   1901 		/*---------------------------------------------------------------------
   1902 		Wait a while, polling the IPX service routines, to give our ACK
   1903 		a chance to get to the other system.  If he doesn't get our ACK, he'll
   1904 		be waiting the whole time we load MIX files.
   1905 		---------------------------------------------------------------------*/
   1906 		i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)60);
   1907 		starttime = TickCount.Time();
   1908 		while (TickCount.Time() - starttime < (unsigned)i) {
   1909 			Ipx.Service();
   1910 		}
   1911 	}
   1912 
   1913 	/*------------------------------------------------------------------------
   1914 	Init network timing values, using previous response times as a measure
   1915 	of what our retry delta & timeout should be.
   1916 	------------------------------------------------------------------------*/
   1917 	Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
   1918 		Ipx.Global_Response_Time() * 4);
   1919 
   1920 	/*------------------------------------------------------------------------
   1921 	Clear all lists
   1922 	------------------------------------------------------------------------*/
   1923 	Clear_Game_List(&gamelist);
   1924 	Clear_Player_List(&playerlist);
   1925 
   1926 	/*------------------------------------------------------------------------
   1927 	Restore screen
   1928 	------------------------------------------------------------------------*/
   1929 	Hide_Mouse();
   1930 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   1931 	Blit_Hid_Page_To_Seen_Buff();
   1932 	Show_Mouse();
   1933 
   1934 	return(rc);
   1935 }
   1936 
   1937 
   1938 /***************************************************************************
   1939  * Clear_Game_List -- Clears the game-name listbox & 'Games' Vector        *
   1940  *                                                                         *
   1941  * Assumes each entry in 'Games' & the list box have been allocated		   *
   1942  * separately.																				   *
   1943  *                                                                         *
   1944  * INPUT:                                                                  *
   1945  *		gamelist		ptr to list box													   *
   1946  *                                                                         *
   1947  * OUTPUT:                                                                 *
   1948  *		none																					   *
   1949  *                                                                         *
   1950  * WARNINGS:                                                               *
   1951  *		none																					   *
   1952  *                                                                         *
   1953  * HISTORY:                                                                *
   1954  *=========================================================================*/
   1955 static void Clear_Game_List (ListClass *gamelist)
   1956 {
   1957 	char * item;
   1958 	int i;
   1959 
   1960 	/*------------------------------------------------------------------------
   1961 	Clear the list box
   1962 	------------------------------------------------------------------------*/
   1963 	while (gamelist->Count()) {
   1964 		item = (char *)(gamelist->Get_Item (0));
   1965 		gamelist->Remove_Item(item);
   1966 		delete [] item;
   1967 	}
   1968 	gamelist->Flag_To_Redraw();
   1969 
   1970 	/*------------------------------------------------------------------------
   1971 	Clear the 'Games' Vector
   1972 	------------------------------------------------------------------------*/
   1973 	for (i = 0; i < Games.Count(); i++)
   1974 		delete Games[i];
   1975 
   1976 	Games.Clear();
   1977 
   1978 }	/* end of Clear_Game_List */
   1979 
   1980 
   1981 /***************************************************************************
   1982  * Clear_Player_List -- Clears the player-name listbox & Vector     		   *
   1983  *                                                                         *
   1984  * Assumes each entry in 'Players' & the list box have been allocated		*
   1985  * separately.																				   *
   1986  *                                                                         *
   1987  * INPUT:                                                                  *
   1988  *		playerlist		ptr to list box												   *
   1989  *                                                                         *
   1990  * OUTPUT:                                                                 *
   1991  *		none																					   *
   1992  *                                                                         *
   1993  * WARNINGS:                                                               *
   1994  *		none																					   *
   1995  *                                                                         *
   1996  * HISTORY:                                                                *
   1997  *=========================================================================*/
   1998 static void Clear_Player_List (ListClass *playerlist)
   1999 {
   2000 	char * item;
   2001 	int i;
   2002 
   2003 	/*------------------------------------------------------------------------
   2004 	Clear the list box
   2005 	------------------------------------------------------------------------*/
   2006 	while (playerlist->Count()) {
   2007 		item = (char *)(playerlist->Get_Item(0));
   2008 		playerlist->Remove_Item(item);
   2009 		delete [] item;
   2010 	}
   2011 	playerlist->Flag_To_Redraw();
   2012 
   2013 	/*------------------------------------------------------------------------
   2014 	Clear the 'Players' Vector
   2015 	------------------------------------------------------------------------*/
   2016 	for (i = 0; i < Players.Count(); i++)
   2017 		delete Players[i];
   2018 
   2019 	Players.Clear();
   2020 
   2021 }	/* end of Clear_Player_List */
   2022 
   2023 
   2024 /***************************************************************************
   2025  * Request_To_Join -- Sends a JOIN request packet to game owner            *
   2026  *                                                                         *
   2027  * Regardless of the return code, the Join Dialog will need to be redrawn	*
   2028  * after calling this routine.															*
   2029  *                                                                         *
   2030  * INPUT:                                                                  *
   2031  *		playername		player's name														*
   2032  *		join_index		index of game we're joining									*
   2033  *		playerlist		listbox containing other players' names					*
   2034  *		house				requested house													*
   2035  *		color				requested color													*
   2036  *                                                                         *
   2037  * OUTPUT:                                                                 *
   2038  *		1 = Packet sent, 0 = wasn't														*
   2039  *                                                                         *
   2040  * WARNINGS:                                                               *
   2041  *		none.																						*
   2042  *                                                                         *
   2043  * HISTORY:                                                                *
   2044  *=========================================================================*/
   2045 static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
   2046 	HousesType house, int color)
   2047 {
   2048 	int i;
   2049 
   2050 	playerlist = playerlist;	// shaddup, Mr stupid compiler!
   2051 
   2052 	/*
   2053 	--------------------------- Validate join_index --------------------------
   2054 	*/
   2055 	if ( (Games.Count()==0) || join_index > Games.Count() || join_index < 0) {
   2056 		CCMessageBox().Process (TXT_NOTHING_TO_JOIN);
   2057 		return(false);
   2058 	}
   2059 
   2060 	/*
   2061 	----------------------- Force user to enter a name -----------------------
   2062 	*/
   2063 	if (strlen(playername)==0) {
   2064 		CCMessageBox().Process (TXT_NAME_ERROR);
   2065 		return(false);
   2066 	}
   2067 
   2068 	/*
   2069 	------------------------- The game must be open --------------------------
   2070 	*/
   2071 	if (!Games[join_index]->Game.IsOpen) {
   2072 		CCMessageBox().Process(TXT_GAME_IS_CLOSED);
   2073 		return (false);
   2074 	}
   2075 
   2076 	/*
   2077 	------------------------ Make sure name is unique ------------------------
   2078 	*/
   2079 	for (i = 0; i < Players.Count(); i++) {
   2080 		if (!stricmp(playername, Players[i]->Name)) {
   2081 			CCMessageBox().Process (TXT_NAME_MUSTBE_UNIQUE);
   2082 			return(false);
   2083 		}
   2084 	}
   2085 
   2086 	/*
   2087 	----------------------------- Check version #'s --------------------------
   2088 	*/
   2089 	int v;
   2090 #ifdef PATCH
   2091 	if (IsV107) {
   2092 		v = 1;
   2093 	} else {
   2094 		v = 2;
   2095 	}
   2096 #else
   2097 	v = Version_Number();
   2098 #endif
   2099 	if (Games[join_index]->Game.Version > v) {
   2100 		CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
   2101 		return(false);
   2102 	} else {
   2103 		if (Games[join_index]->Game.Version < v) {
   2104 			CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
   2105 			return(false);
   2106 		}
   2107 	}
   2108 
   2109 	/*
   2110 	----------------------------- Save game name -----------------------------
   2111 	*/
   2112 	strcpy (MPlayerName,playername);
   2113 
   2114 	/*
   2115 	----------------------- Send packet to game's owner ----------------------
   2116 	*/
   2117 	memset (&GPacket, 0, sizeof(GlobalPacketType));
   2118 
   2119 	GPacket.Command = NET_QUERY_JOIN;
   2120 	strcpy (GPacket.Name, MPlayerName);
   2121 	GPacket.PlayerInfo.House = house;
   2122 	GPacket.PlayerInfo.Color = color;
   2123 
   2124 	Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   2125 		&(Games[join_index]->Address));
   2126 
   2127 	return(true);
   2128 }
   2129 
   2130 
   2131 /***********************************************************************************************
   2132  * Send_Join_Queries -- sends queries for the Join Dialog												  *
   2133  *                                                                         						  *
   2134  * This routine [re]sends the queries related to the Join Dialog:										  *
   2135  * - NET_QUERY_GAME																									  *
   2136  * - NET_QUERY_PLAYER for the game currently selected (if there is one)								  *
   2137  *																															  *
   2138  * The queries are "staggered" in time so they aren't all sent at once; otherwise, we'd		  *
   2139  * be inundated with reply packets & we'd miss some (even though the replies will require		  *
   2140  * ACK's).																												  *
   2141  *                                                                         						  *
   2142  * INPUT:                                                                  						  *
   2143  *		curgame		index of currently-selected game; -1 = none											  *
   2144  *		gamenow		if 1, will immediately send the game query											  *
   2145  *		playernow	if 1, will immediately send the player query for currently-selected game	  *
   2146  *                                                                         						  *
   2147  * OUTPUT:                                                                 						  *
   2148  *		none.																												  *
   2149  *                                                                         						  *
   2150  * WARNINGS:                                                               						  *
   2151  *		none.																												  *
   2152  *                                                                         						  *
   2153  * HISTORY:                                                                						  *
   2154  *   02/14/1995 BR : Created.                                              						  *
   2155  *   04/15/1995 BRR : Created.                                                                 *
   2156  *=============================================================================================*/
   2157 static void Send_Join_Queries(int curgame, int gamenow, int playernow)
   2158 {
   2159 	static int lasttime1 = 0;		// time since last Game query sent out
   2160 	static int lasttime2 = 0;		// time since last Player query sent out
   2161 
   2162 	/*------------------------------------------------------------------------
   2163 	Send the game-name query if the time has expired, or we're told to do
   2164 	it right now
   2165 	------------------------------------------------------------------------*/
   2166 	if ( (TickCount.Time() - lasttime1 > 120) || gamenow) {
   2167 		lasttime1 = TickCount.Time();
   2168 
   2169 		memset (&GPacket, 0, sizeof(GlobalPacketType));
   2170 
   2171 		GPacket.Command = NET_QUERY_GAME;
   2172 
   2173 		Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
   2174 
   2175 		/*.....................................................................
   2176 		If the user specified a remote server address, broadcast over that
   2177 		network, too.
   2178 		.....................................................................*/
   2179 		if (IsBridge)
   2180 			Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   2181 				&BridgeNet);
   2182 	}
   2183 
   2184 	/*------------------------------------------------------------------------
   2185 	Send the player query for the game currently clicked on, if the time has
   2186 	expired and there is a currently-selected game, or we're told to do it
   2187 	right now
   2188 	------------------------------------------------------------------------*/
   2189 	if ( (curgame != -1) && curgame < Games.Count() &&
   2190 		((TickCount.Time() - lasttime2 > 35) || playernow) ) {
   2191 		lasttime2 = TickCount.Time();
   2192 
   2193 		memset (&GPacket, 0, sizeof(GlobalPacketType));
   2194 
   2195 		GPacket.Command = NET_QUERY_PLAYER;
   2196 		strcpy (GPacket.Name, Games[curgame]->Name);
   2197 
   2198 		Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
   2199 
   2200 		/*.....................................................................
   2201 		If the user specified a remote server address, broadcast over that
   2202 		network, too.
   2203 		.....................................................................*/
   2204 		if (IsBridge)
   2205 			Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   2206 				&BridgeNet);
   2207 	}
   2208 
   2209 }	/* end of Send_Join_Queries */
   2210 
   2211 
   2212 /***********************************************************************************************
   2213  * Get_Join_Responses -- sends queries for the Join Dialog												  *
   2214  *                                                                         						  *
   2215  * This routine polls the Global Channel to see if there are any incoming packets;				  *
   2216  * if so, it processes them.  This routine can change the state of the Join Dialog, or			  *
   2217  * the contents of the list boxes, based on what the packet is.										  *
   2218  *                                                                         						  *
   2219  * The list boxes are passed in as pointers; they can't be made globals, because they			  *
   2220  * can't be constructed, because they require shape pointers to the arrow buttons, and			  *
   2221  * the mix files won't have been initialized when the global variables' constructors are		  *
   2222  * called.																												  *
   2223  *                                                                         						  *
   2224  * This routine sets the globals 																				  *
   2225  *		MPlayerHouse			(from NET_CONFIRM_JOIN)															  *
   2226  *		MPlayerColorIdx		(from NET_CONFIRM_JOIN)															  *
   2227  *		MPlayerBases			(from NET_GAME_OPTIONS)															  *
   2228  *		MPlayerTiberium		(from NET_GAME_OPTIONS)															  *
   2229  *		MPlayerGoodies			(from NET_GAME_OPTIONS)															  *
   2230  *		MPlayerGhosts			(from NET_GAME_OPTIONS)															  *
   2231  *		ScenarioIdx				(from NET_GAME_OPTIONS; -1 = scenario not found)						  *
   2232  *                                                                         						  *
   2233  * INPUT:                                                                  						  *
   2234  *		joinstate		current state of Join Dialog															  *
   2235  *		gamelist			list box containing game names														  *
   2236  *		playerlist		list box containing player names for the currently-selected game			  *
   2237  *		join_index		index of the game we've joined or are asking to join							  *
   2238  *                                                                         						  *
   2239  * OUTPUT:                                                                 						  *
   2240  *		Event that occurred																							  *
   2241  *                                                                         						  *
   2242  * WARNINGS:                                                               						  *
   2243  *		none.																												  *
   2244  *                                                                         						  *
   2245  * HISTORY:                                                                						  *
   2246  *   02/14/1995 BR : Created.                                              						  *
   2247  *   04/15/1995 BRR : Created.                                                                 *
   2248  *=============================================================================================*/
   2249 static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
   2250 	ColorListClass *playerlist, int join_index)
   2251 {
   2252 	int rc;
   2253 	char * item;						// general-purpose string
   2254 	NodeNameType *who;				// node to add to Games or Players
   2255 	int i;
   2256 	int found;
   2257 	JoinEventType retcode = EV_NONE;
   2258 	char txt[80];
   2259 	int color;
   2260 	unsigned short magic_number;
   2261 	unsigned short	crc;
   2262 
   2263 	/*------------------------------------------------------------------------
   2264 	If there is no incoming packet, just return
   2265 	------------------------------------------------------------------------*/
   2266 	rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
   2267 	if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER)
   2268 		return(EV_NONE);
   2269 
   2270 	/*------------------------------------------------------------------------
   2271 	If we're joined in a game, handle the packet in a standard way; otherwise,
   2272 	don't answer standard queries.
   2273 	------------------------------------------------------------------------*/
   2274 	if ( (*joinstate)==JOIN_CONFIRMED &&
   2275 		Process_Global_Packet(&GPacket,&GAddress)!=0)
   2276 		return(EV_NONE);
   2277 
   2278 	/*------------------------------------------------------------------------
   2279 	NET_ANSWER_GAME:  Another system is answering our GAME query, so add that
   2280 	system to our list box if it's new.
   2281 	------------------------------------------------------------------------*/
   2282 	if (GPacket.Command==NET_ANSWER_GAME) {
   2283 		/*.....................................................................
   2284 		See if this name is unique
   2285 		.....................................................................*/
   2286 		retcode = EV_NONE;
   2287 		found = 0;
   2288 		for (i = 0; i < Games.Count(); i++) {
   2289 			if (!strcmp(Games[i]->Name, GPacket.Name)) {
   2290 				found = 1;
   2291 				/*...............................................................
   2292 				If name was found, update the node's time stamp & IsOpen flag.
   2293 				...............................................................*/
   2294 				Games[i]->Game.LastTime = TickCount.Time();
   2295 				if (Games[i]->Game.IsOpen != GPacket.GameInfo.IsOpen) {
   2296 					item = (char *)gamelist->Get_Item(i);
   2297 					if (GPacket.GameInfo.IsOpen) {
   2298 						sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
   2299 					} else {
   2300 						sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
   2301 					}
   2302 					Games[i]->Game.IsOpen = GPacket.GameInfo.IsOpen;
   2303 					gamelist->Flag_To_Redraw();
   2304 					/*............................................................
   2305 					If this game has gone from closed to open, copy the responder's
   2306 					address into our Game slot, since the guy responding to this
   2307 					must be game owner.
   2308 					............................................................*/
   2309 					if (Games[i]->Game.IsOpen)
   2310 						Games[i]->Address = GAddress;
   2311 				}
   2312 				break;
   2313 			}
   2314 		}
   2315 		/*.....................................................................
   2316 		name not found (or addresses are different); add it to 'Games'
   2317 		.....................................................................*/
   2318 		if (found==0) {
   2319 			/*..................................................................
   2320 			Create a new node structure, fill it in, add it to 'Games'
   2321 			..................................................................*/
   2322 			who = new NodeNameType;
   2323 			strcpy(who->Name, GPacket.Name);
   2324 			who->Address = GAddress;
   2325 			who->Game.Version = GPacket.GameInfo.Version;
   2326 			who->Game.IsOpen = GPacket.GameInfo.IsOpen;
   2327 			who->Game.LastTime = TickCount.Time();
   2328 			Games.Add (who);
   2329 
   2330 			/*..................................................................
   2331 			Create a string for "xxx's Game", leaving room for brackets around
   2332 			the string if it's a closed game
   2333 			..................................................................*/
   2334 			item = new char [MPLAYER_NAME_MAX + 9];
   2335 			if (GPacket.GameInfo.IsOpen) {
   2336 				sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
   2337 			} else {
   2338 				sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
   2339 			}
   2340 			gamelist->Add_Item(item);
   2341 
   2342 			retcode = EV_NEW_GAME;
   2343 		}
   2344 	}
   2345 
   2346 	/*------------------------------------------------------------------------
   2347 	NET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add it
   2348 	to our player list box & the Player Vector if it's new
   2349 	------------------------------------------------------------------------*/
   2350 	else if (GPacket.Command==NET_ANSWER_PLAYER) {
   2351 		/*.....................................................................
   2352 		See if this name is unique
   2353 		.....................................................................*/
   2354 		retcode = EV_NONE;
   2355 		found = 0;
   2356 		for (i = 0; i < Players.Count(); i++) {
   2357 			/*..................................................................
   2358 			If the address is already present, re-copy their name, color &
   2359 			house into the existing entry, in case they've changed it without
   2360 			our knowledge; set the 'found' flag so we won't create a new entry.
   2361 			..................................................................*/
   2362 			if (Players[i]->Address==GAddress) {
   2363 				strcpy(Players[i]->Name, GPacket.Name);
   2364 				Players[i]->Player.House = GPacket.PlayerInfo.House;
   2365 				Players[i]->Player.Color = GPacket.PlayerInfo.Color;
   2366 				playerlist->Colors[i] = MPlayerTColors[GPacket.PlayerInfo.Color];
   2367 				found = 1;
   2368 				break;
   2369 			}
   2370 		}
   2371 		/*.....................................................................
   2372 		Don't add this player if he's not part of the game that's selected.
   2373 		.....................................................................*/
   2374 		i = gamelist->Current_Index();
   2375 		if (Games.Count() && GPacket.PlayerInfo.NameCRC != Compute_Name_CRC(Games[i]->Name))
   2376 			found = 1;
   2377 
   2378 		/*
   2379 		** Dont add this player if its really me! (hack, hack)
   2380 		*/
   2381 		if (!strcmp(GPacket.Name, MPlayerName)){
   2382 			found = 1;
   2383 		}
   2384 
   2385 
   2386 		/*.....................................................................
   2387 		name not found (or address didn't match); add to player list box & Vector
   2388 		.....................................................................*/
   2389 		if (found==0) {
   2390 			/*..................................................................
   2391 			Create & add a node to the Vector
   2392 			..................................................................*/
   2393 			who = new NodeNameType;
   2394 			strcpy(who->Name, GPacket.Name);
   2395 			who->Address = GAddress;
   2396 			who->Player.House = GPacket.PlayerInfo.House;
   2397 			who->Player.Color = GPacket.PlayerInfo.Color;
   2398 			Players.Add (who);
   2399 
   2400 			/*..................................................................
   2401 			Create & add a string to the list box
   2402 			..................................................................*/
   2403 			item = new char [MPLAYER_NAME_MAX + 4];
   2404 			if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
   2405 				sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
   2406 			} else {
   2407 				sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
   2408 			}
   2409 			playerlist->Add_Item(item, MPlayerTColors[who->Player.Color]);
   2410 
   2411 			retcode = EV_NEW_PLAYER;
   2412 		}
   2413 	}
   2414 
   2415 	/*------------------------------------------------------------------------
   2416 	NET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us as
   2417 	being confirmed, and start answering queries from other systems
   2418 	------------------------------------------------------------------------*/
   2419 	else if (GPacket.Command==NET_CONFIRM_JOIN) {
   2420 		if ( (*joinstate) != JOIN_CONFIRMED) {
   2421 			strcpy (MPlayerGameName, GPacket.Name);
   2422 			MPlayerHouse = GPacket.PlayerInfo.House;
   2423 			MPlayerColorIdx = GPacket.PlayerInfo.Color;
   2424 
   2425 			(*joinstate) = JOIN_CONFIRMED;
   2426 			retcode = EV_STATE_CHANGE;
   2427 		}
   2428 	}
   2429 
   2430 	/*------------------------------------------------------------------------
   2431 	NET_REJECT_JOIN: The game owner has turned down our JOIN query; restore
   2432 	the dialog state to its first pop-up state.  Broadcast a sign-off to
   2433 	tell all other systems that I'm no longer a part of any game; this way,
   2434 	I'll be properly removed from their dialogs.
   2435 	------------------------------------------------------------------------*/
   2436 	else if (GPacket.Command==NET_REJECT_JOIN) {
   2437 		if ( (*joinstate) != JOIN_REJECTED) {
   2438 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   2439 
   2440 			GPacket.Command = NET_SIGN_OFF;
   2441 			strcpy (GPacket.Name,MPlayerName);
   2442 
   2443 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
   2444 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
   2445 
   2446 			if (IsBridge) {
   2447 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   2448 					&BridgeNet);
   2449 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   2450 					&BridgeNet);
   2451 			}
   2452 
   2453 			while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   2454 
   2455 			MPlayerGameName[0] = 0;
   2456 
   2457 			(*joinstate) = JOIN_REJECTED;
   2458 			retcode = EV_STATE_CHANGE;
   2459 		}
   2460 	}
   2461 
   2462 	/*------------------------------------------------------------------------
   2463 	NET_GAME_OPTIONS: The game owner has changed the game options & is sending
   2464 	us the new values.
   2465 	------------------------------------------------------------------------*/
   2466 	else if (GPacket.Command==NET_GAME_OPTIONS) {
   2467 		if ( (*joinstate)==JOIN_CONFIRMED) {
   2468 			MPlayerCredits = GPacket.ScenarioInfo.Credits;
   2469 			MPlayerBases = GPacket.ScenarioInfo.IsBases;
   2470 			MPlayerTiberium = GPacket.ScenarioInfo.IsTiberium;
   2471 			MPlayerGoodies = GPacket.ScenarioInfo.IsGoodies;
   2472 			MPlayerGhosts = GPacket.ScenarioInfo.IsGhosties;
   2473 			BuildLevel = GPacket.ScenarioInfo.BuildLevel;
   2474 			MPlayerUnitCount = GPacket.ScenarioInfo.UnitCount;
   2475 			Seed = GPacket.ScenarioInfo.Seed;
   2476 			Special = GPacket.ScenarioInfo.Special;
   2477 			Options.GameSpeed = GPacket.ScenarioInfo.GameSpeed;
   2478 
   2479 			if (MPlayerTiberium) {
   2480 				Special.IsTGrowth = 1;
   2481 				Special.IsTSpread = 1;
   2482 			} else {
   2483 				Special.IsTGrowth = 0;
   2484 				Special.IsTSpread = 0;
   2485 			}
   2486 
   2487 			if (Winsock.Get_Connected()){
   2488 				ScenarioIdx = GPacket.ScenarioInfo.Scenario;
   2489 			}else{
   2490 
   2491 				ScenarioIdx = -1;
   2492 				for (i = 0; i < MPlayerFilenum.Count(); i++) {
   2493 					if (GPacket.ScenarioInfo.Scenario == MPlayerFilenum[i])
   2494 						ScenarioIdx = i;
   2495 				}
   2496 			}
   2497 
   2498 			retcode = EV_GAME_OPTIONS;
   2499 		}
   2500 	}
   2501 
   2502 	/*------------------------------------------------------------------------
   2503 	NET_SIGN_OFF: Another system is signing off: search for that system in
   2504 	both the game list & player list, & remove it if found
   2505 	------------------------------------------------------------------------*/
   2506 	else if (GPacket.Command==NET_SIGN_OFF) {
   2507 		/*.....................................................................
   2508 		Remove this name from the list of games
   2509 		.....................................................................*/
   2510 		for (i = 0; i < Games.Count(); i++) {
   2511 			if (!strcmp(Games[i]->Name, GPacket.Name) &&
   2512 				Games[i]->Address==GAddress) {
   2513 				/*...............................................................
   2514 				If the system signing off is the currently-selected list
   2515 				item, clear the player list since that game is no longer
   2516 				forming.
   2517 				...............................................................*/
   2518 				if (i==gamelist->Current_Index()) {
   2519 					Clear_Player_List (playerlist);
   2520 				}
   2521 
   2522 				/*...............................................................
   2523 				If the system signing off was the owner of our game, mark
   2524 				ourselves as rejected
   2525 				...............................................................*/
   2526 				if ( (*joinstate) > JOIN_NOTHING && i==join_index) {
   2527 					(*joinstate) = JOIN_REJECTED;
   2528 					retcode = EV_STATE_CHANGE;
   2529 				}
   2530 
   2531 				/*
   2532 				....................... Set my return code ......................
   2533 				*/
   2534 				if (retcode == EV_NONE) {
   2535 					if (i <= gamelist->Current_Index()) {
   2536 						retcode = EV_GAME_SIGNOFF;
   2537 					} else {
   2538 						retcode = EV_PLAYER_SIGNOFF;
   2539 					}
   2540 				}
   2541 
   2542 				/*
   2543 				................. Remove game name from game list ...............
   2544 				*/
   2545 				Games.Delete(Games[i]);
   2546 				item = (char *)(gamelist->Get_Item (i));
   2547 				gamelist->Remove_Item (item);
   2548 				delete [] item;
   2549 				gamelist->Flag_To_Redraw();
   2550 
   2551 			}
   2552 		}
   2553 		/*.....................................................................
   2554 		Remove this name from the list of players
   2555 		.....................................................................*/
   2556 		for (i = 0; i < Players.Count(); i++) {
   2557 			/*
   2558 			..................... Name found; remove it .....................
   2559 			*/
   2560 			if (Players[i]->Address==GAddress) {
   2561 				item = (char *)(playerlist->Get_Item(i));
   2562 				playerlist->Remove_Item(item);
   2563 				delete [] item;
   2564 				Players.Delete(Players[i]);
   2565 				playerlist->Flag_To_Redraw();
   2566 
   2567 				if (retcode == EV_NONE)
   2568 					retcode = EV_PLAYER_SIGNOFF;
   2569 			}
   2570 		}
   2571 	}
   2572 
   2573 	/*------------------------------------------------------------------------
   2574 	NET_GO: The game's owner is signalling us to start playing.
   2575 	------------------------------------------------------------------------*/
   2576 	else if (GPacket.Command==NET_GO) {
   2577 		if ( (*joinstate)==JOIN_CONFIRMED) {
   2578 			MPlayerMaxAhead = GPacket.ResponseTime.OneWay;
   2579 			(*joinstate) = JOIN_GAME_START;
   2580 			retcode = EV_STATE_CHANGE;
   2581 CCDebugString ("C&C95 - Received the 'GO' packet\n");
   2582 		}
   2583 	}
   2584 
   2585 	/*------------------------------------------------------------------------
   2586 	NET_MESSAGE: Someone is sending us a message
   2587 	------------------------------------------------------------------------*/
   2588 	else if (GPacket.Command==NET_MESSAGE) {
   2589 		sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
   2590 		magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
   2591 		crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
   2592 		color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
   2593 		Messages.Add_Message (txt, MPlayerTColors[color],
   2594 			TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
   2595 		retcode = EV_MESSAGE;
   2596 	}
   2597 
   2598 	/*------------------------------------------------------------------------
   2599 	NET_PING: Someone is pinging me to get a response time measure (will only
   2600 	happen after I've joined a game).  Do nothing; the IPX Manager will handle
   2601 	sending an ACK, and updating the response time measurements.
   2602 	------------------------------------------------------------------------*/
   2603 	else if (GPacket.Command==NET_PING) {
   2604 		retcode = EV_NONE;
   2605 	}
   2606 
   2607 	/*------------------------------------------------------------------------
   2608 	Default case: nothing happened.  (This case will be hit every time I
   2609 	receive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)
   2610 	------------------------------------------------------------------------*/
   2611 	else {
   2612 		retcode = EV_NONE;
   2613 	}
   2614 
   2615 	return(retcode);
   2616 }
   2617 
   2618 
   2619 /***********************************************************************************************
   2620  * Net_New_Dialog -- lets user start a new game																  *
   2621  *                                                                         						  *
   2622  * This dialog shows a list of who's requesting to join this game, and lets						  *
   2623  * the game initiator selectively approve each user.														  *
   2624  *                                                                         						  *
   2625  *    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿                       						  *
   2626  *    ³              New Network Game              ³                       						  *
   2627  *    ³                                            ³                       						  *
   2628  *    ³     Players               Scenario         ³   													  *
   2629  *    ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ 														  *
   2630  *    ³ ³ Boffo       ³³   ³ Hell's Kitchen   ³³ ³ 														  *
   2631  *    ³ ³ Bozo        ÃÄ´   ³ Heaven's Gate    ÃÄ´ ³														  *
   2632  *    ³ ³ Bonzo       ³ ³   ³      ...         ³ ³ ³														  *
   2633  *    ³ ³             ÃÄ´   ³                  ÃÄ´ ³ 														  *
   2634  *    ³ ³             ³³   ³                  ³³ ³ 														  *
   2635  *    ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ 														  *
   2636  *    ³     [Reject]             Count:--- ##      ³														  *
   2637  *    ³                          Level:--- ##      ³                       						  *
   2638  *    ³                                            ³                       						  *
   2639  *    ³               Credits: _____               ³                             				  *
   2640  *    ³       [  Bases   ]   [   Crates   ]        ³                          					  *
   2641  *    ³       [ Tiberium ]   [ AI Players ]        ³                           					  *
   2642  *    ³                                            ³                       						  *
   2643  *    ³              [OK]    [Cancel]              ³                       						  *
   2644  *    ³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿   ³                       						  *
   2645  *    ³  ³                                     ³   ³                       						  *
   2646  *    ³  ³                                     ³   ³                       						  *
   2647  *    ³  ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ   ³                       						  *
   2648  *    ³               [Send Message]               ³                       						  *
   2649  *    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ                       						  *
   2650  *                                                                         						  *
   2651  * INPUT:                                                                  						  *
   2652  *		none.																												  *
   2653  *                                                                         						  *
   2654  * OUTPUT:                                                                 						  *
   2655  *		true = success, false = cancel																			  *
   2656  *                                                                         						  *
   2657  * WARNINGS:                                                               						  *
   2658  *		MPlayerName & MPlayerGameName must contain this player's name.									  *
   2659  *                                                                         						  *
   2660  * HISTORY:                                                                						  *
   2661  *   02/14/1995 BR : Created.                                              						  *
   2662  *=============================================================================================*/
   2663 static int Net_New_Dialog(void)
   2664 {
   2665 /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
   2666 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
   2667 	/*........................................................................
   2668 	Dialog & button dimensions
   2669 	........................................................................*/
   2670 		//D_DIALOG_W = 281;											// dialog width
   2671 	int d_dialog_w = 287*factor;											// dialog width
   2672 	int d_dialog_h = 177*factor;											// dialog height
   2673 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
   2674 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
   2675 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
   2676 
   2677 	int d_txt6_h = 6*factor+1;												// ht of 6-pt text
   2678 	int d_margin1 = 5*factor;												// margin width/height
   2679 	int d_margin2 = 2*factor;												// margin width/height
   2680 
   2681 	//d_playerlist_w = 100;
   2682 	int d_playerlist_w = 106*factor;
   2683 	int d_playerlist_h = 27*factor;
   2684 	int d_playerlist_x = d_dialog_x + d_margin1;
   2685 	int d_playerlist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
   2686 
   2687 	int d_scenariolist_w = 162*factor;
   2688 	int d_scenariolist_h = 27*factor;
   2689 	int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_scenariolist_w;
   2690 	int d_scenariolist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
   2691 
   2692 #if (GERMAN | FRENCH)
   2693 	int d_reject_w = 55*factor;
   2694 #else
   2695 	int d_reject_w = 45*factor;
   2696 #endif
   2697 	int d_reject_h = 9*factor;
   2698 	int d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);
   2699 	int d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;
   2700 
   2701 	int d_count_w = 25*factor;
   2702 	int d_count_h = d_txt6_h;
   2703 	int d_count_x = d_scenariolist_x + (d_scenariolist_w / 2);
   2704 	int d_count_y = d_scenariolist_y + d_scenariolist_h + d_margin2;
   2705 
   2706 	int d_level_w = 25*factor;
   2707 	int d_level_h = d_txt6_h;
   2708 	int d_level_x = d_scenariolist_x + (d_scenariolist_w / 2);
   2709 	int d_level_y = d_count_y + d_count_h;
   2710 
   2711 	int d_credits_w = ((CREDITSBUF_MAX - 1) * 7*factor) + 4*factor;
   2712 	//int d_credits_w = ((CREDITSBUF_MAX - 1) * 6*factor) + 3*factor;
   2713 	int d_credits_h = 9*factor;
   2714 	int d_credits_x = d_dialog_cx + 2*factor;
   2715 	int d_credits_y = d_level_y + d_level_h + d_margin1;
   2716 
   2717 #if (GERMAN | FRENCH)
   2718 	int d_bases_w = 120*factor;//bga:100;
   2719 #else
   2720 	int d_bases_w = 100*factor;
   2721 #endif
   2722 	int d_bases_h = 9*factor;
   2723 	int d_bases_x = d_dialog_cx - d_bases_w - d_margin2;
   2724 	int d_bases_y = d_credits_y + d_credits_h + d_margin2;
   2725 
   2726 #if (GERMAN | FRENCH)
   2727 	int d_tiberium_w = 120*factor;
   2728 #else
   2729 	int d_tiberium_w = 100*factor;
   2730 #endif
   2731 	int d_tiberium_h = 9*factor;
   2732 	int d_tiberium_x = d_dialog_cx - d_bases_w - d_margin2;
   2733 	int d_tiberium_y = d_bases_y + d_bases_h + d_margin2;
   2734 
   2735 #if (GERMAN | FRENCH)
   2736 	int d_goodies_w = 120*factor;
   2737 #else
   2738 	int d_goodies_w = 100*factor;
   2739 #endif
   2740 	int d_goodies_h = 9*factor;
   2741 	int d_goodies_x = d_dialog_cx + d_margin2;
   2742 	int d_goodies_y = d_credits_y + d_credits_h + d_margin2;
   2743 
   2744 #if (GERMAN | FRENCH)
   2745 	int d_ghosts_w = 120*factor;
   2746 #else
   2747 	int d_ghosts_w = 100*factor;
   2748 #endif
   2749 	int d_ghosts_h = 9*factor;
   2750 	int d_ghosts_x = d_dialog_cx + d_margin2;
   2751 	int d_ghosts_y = d_goodies_y + d_goodies_h + d_margin2;
   2752 
   2753 	int d_ok_w = 45*factor;
   2754 	int d_ok_h = 9*factor;
   2755 	int d_ok_x = d_dialog_cx - d_margin2 - (d_bases_w / 2) - (d_ok_w / 2);
   2756 	int d_ok_y = d_ghosts_y + d_ghosts_h + d_margin1;
   2757 
   2758 #if (GERMAN | FRENCH)
   2759 	int d_cancel_w = 50*factor;
   2760 #else
   2761 	int d_cancel_w = 45*factor;
   2762 #endif
   2763 	int d_cancel_h = 9*factor;
   2764 	int d_cancel_x = d_dialog_cx + d_margin2 + (d_goodies_w / 2) - (d_cancel_w / 2);
   2765 	int d_cancel_y = d_ghosts_y + d_ghosts_h + d_margin1;
   2766 
   2767 	int d_message_w = d_dialog_w - (d_margin1 * 2);
   2768 	int d_message_h = 34*factor;
   2769 	int d_message_x = d_dialog_x + d_margin1;
   2770 	int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
   2771 
   2772 	int d_send_w = 80*factor;
   2773 	int d_send_h = 9*factor;
   2774 	int d_send_x = d_dialog_cx - (d_send_w / 2);
   2775 	int d_send_y = d_message_y + d_message_h + d_margin2;
   2776 
   2777 	/*........................................................................
   2778 	Button Enumerations
   2779 	........................................................................*/
   2780 	enum {
   2781 		BUTTON_PLAYERLIST = 100,
   2782 		BUTTON_SCENARIOLIST,
   2783 		BUTTON_REJECT,
   2784 		BUTTON_COUNT,
   2785 		BUTTON_LEVEL,
   2786 		BUTTON_CREDITS,
   2787 		BUTTON_BASES,
   2788 		BUTTON_TIBERIUM,
   2789 		BUTTON_GOODIES,
   2790 		BUTTON_GHOSTS,
   2791 		BUTTON_OK,
   2792 		BUTTON_CANCEL,
   2793 		BUTTON_SEND,
   2794 	};
   2795 
   2796 	/*........................................................................
   2797 	Redraw values: in order from "top" to "bottom" layer of the dialog
   2798 	........................................................................*/
   2799 	typedef enum {
   2800 		REDRAW_NONE = 0,
   2801 		REDRAW_UNIT_COUNT,
   2802 		REDRAW_MESSAGE,
   2803 		REDRAW_BUTTONS,
   2804 		REDRAW_BACKGROUND,
   2805 		REDRAW_ALL = REDRAW_BACKGROUND
   2806 	} RedrawType;
   2807 
   2808 	/*........................................................................
   2809 	Dialog variables
   2810 	........................................................................*/
   2811 	RedrawType display = REDRAW_ALL;		// redraw level
   2812 	bool process = true;						// process while true
   2813 	KeyNumType input;
   2814 
   2815 	char credbuf[CREDITSBUF_MAX];			// for credit edit box
   2816 	int old_cred;								// old value in credits buffer
   2817 	int transmit;								// 1 = re-transmit new game options
   2818 
   2819 	long ok_timer = 0;						// for timing OK button
   2820 	int index;									// index for rejecting a player
   2821 	int rc;
   2822 	int i,j;
   2823 	char *item;
   2824 	int tabs[] = {77*factor};						// tabs for player list box
   2825 
   2826 	long ping_timer = 0;						// for sending Ping packets
   2827 
   2828 	unsigned char tmp_id[MAX_PLAYERS];	// temp storage for sorting player ID's
   2829 	int min_index;								// for sorting player ID's
   2830 	unsigned char min_id;					// for sorting player ID's
   2831 	unsigned char id;							// connection ID
   2832 	char txt[80];
   2833 	JoinEventType whahoppa;					// event generated by received packets
   2834 	static int first_time = 1;				// 1 = 1st time this dialog is run
   2835 
   2836 	int					message_length;
   2837 	int					sent_so_far;
   2838 	unsigned short		magic_number;
   2839 	unsigned short		crc;
   2840 
   2841 	/*........................................................................
   2842 	Buttons
   2843 	........................................................................*/
   2844 	GadgetClass *commands;										// button list
   2845 
   2846 	void const *up_button;
   2847 	void const *down_button;
   2848 
   2849 	if (InMainLoop){
   2850 		up_button = Hires_Retrieve("BTN-UP.SHP");
   2851 		down_button = Hires_Retrieve("BTN-DN.SHP");
   2852 	}else{
   2853 		up_button = Hires_Retrieve("BTN-UP2.SHP");
   2854 		down_button = Hires_Retrieve("BTN-DN2.SHP");
   2855 	}
   2856 
   2857 
   2858 	ColorListClass playerlist(BUTTON_PLAYERLIST,
   2859 		d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
   2860 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2861 		up_button,
   2862 		down_button);
   2863 
   2864 	ListClass scenariolist(BUTTON_SCENARIOLIST,
   2865 		d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h,
   2866 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2867 		up_button,
   2868 		down_button);
   2869 
   2870 	EditClass credit_edt (BUTTON_CREDITS,
   2871 		credbuf, CREDITSBUF_MAX,
   2872 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2873 		d_credits_x, d_credits_y, d_credits_w, d_credits_h, EditClass::ALPHANUMERIC);
   2874 
   2875 	TextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT,
   2876 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2877 //#if (GERMAN | FRENCH)
   2878 //		d_reject_x, d_reject_y);
   2879 //#else
   2880 		d_reject_x, d_reject_y, d_reject_w, d_reject_h);
   2881 //#endif
   2882 
   2883 	GaugeClass countgauge (BUTTON_COUNT,
   2884 		d_count_x, d_count_y, d_count_w, d_count_h);
   2885 
   2886 	GaugeClass levelgauge (BUTTON_LEVEL,
   2887 		d_level_x, d_level_y, d_level_w, d_level_h);
   2888 
   2889 	TextButtonClass basesbtn(BUTTON_BASES, TXT_BASES_OFF,
   2890 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2891 		d_bases_x, d_bases_y, d_bases_w, d_bases_h);
   2892 
   2893 	TextButtonClass tiberiumbtn(BUTTON_TIBERIUM, TXT_TIBERIUM_OFF,
   2894 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2895 		d_tiberium_x, d_tiberium_y, d_tiberium_w, d_tiberium_h);
   2896 
   2897 	TextButtonClass goodiesbtn(BUTTON_GOODIES, TXT_CRATES_OFF,
   2898 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2899 		d_goodies_x, d_goodies_y, d_goodies_w, d_goodies_h);
   2900 
   2901 	TextButtonClass ghostsbtn(BUTTON_GHOSTS, TXT_AI_PLAYERS_OFF,
   2902 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2903 		d_ghosts_x, d_ghosts_y, d_ghosts_w, d_ghosts_h);
   2904 
   2905 	TextButtonClass okbtn(BUTTON_OK, TXT_OK,
   2906 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2907 		d_ok_x, d_ok_y, d_ok_w, d_ok_h);
   2908 
   2909 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
   2910 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2911 //#if (GERMAN | FRENCH)
   2912 //		d_cancel_x, d_cancel_y);
   2913 //#else
   2914 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
   2915 //#endif
   2916 
   2917 	TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
   2918 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   2919 //#if (GERMAN | FRENCH)
   2920 //		d_send_x, d_send_y);
   2921 //#else
   2922 		d_send_x, d_send_y, d_send_w, d_send_h);
   2923 //#endif
   2924 
   2925 	/*
   2926 	------------------------- Build the button list --------------------------
   2927 	*/
   2928 	commands = &playerlist;
   2929 	scenariolist.Add_Tail(*commands);
   2930 	credit_edt.Add_Tail(*commands);
   2931 	rejectbtn.Add_Tail(*commands);
   2932 	countgauge.Add_Tail(*commands);
   2933 	levelgauge.Add_Tail(*commands);
   2934 	basesbtn.Add_Tail(*commands);
   2935 	tiberiumbtn.Add_Tail(*commands);
   2936 	goodiesbtn.Add_Tail(*commands);
   2937 	ghostsbtn.Add_Tail(*commands);
   2938 	okbtn.Add_Tail(*commands);
   2939 	cancelbtn.Add_Tail(*commands);
   2940 	sendbtn.Add_Tail(*commands);
   2941 
   2942 	playerlist.Set_Tabs(tabs);
   2943 
   2944 	/*
   2945 	----------------------------- Various Inits ------------------------------
   2946 	*/
   2947 	/*........................................................................
   2948 	Init dialog values, only the first time through
   2949 	........................................................................*/
   2950 	if (first_time) {
   2951 		MPlayerCredits = 3000;						// init credits & credit buffer
   2952 		MPlayerBases = 1;								// init scenario parameters
   2953 		MPlayerTiberium = 0;
   2954 		MPlayerGoodies = 0;
   2955 		MPlayerGhosts = 0;
   2956 		Special.IsCaptureTheFlag = 0;
   2957 		MPlayerUnitCount = (MPlayerCountMax[MPlayerBases] + MPlayerCountMin[MPlayerBases]) / 2;
   2958 		first_time = 0;
   2959 	}
   2960 
   2961 	/*........................................................................
   2962 	Init button states
   2963 	........................................................................*/
   2964 	if (MPlayerBases) {
   2965 		basesbtn.Turn_On();
   2966 		basesbtn.Set_Text(TXT_BASES_ON);
   2967 	}
   2968 	if (MPlayerTiberium) {
   2969 		tiberiumbtn.Turn_On();
   2970 		tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
   2971 	}
   2972 	if (MPlayerGoodies) {
   2973 		goodiesbtn.Turn_On();
   2974 		goodiesbtn.Set_Text(TXT_CRATES_ON);
   2975 	}
   2976 	if (MPlayerGhosts) {
   2977 		ghostsbtn.Turn_On();
   2978 		ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
   2979 	}
   2980 	if (Special.IsCaptureTheFlag) {
   2981 		MPlayerGhosts = 0;
   2982 		ghostsbtn.Turn_On();
   2983 		ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
   2984 	}
   2985 
   2986 	sprintf(credbuf, "%d", MPlayerCredits);
   2987 	credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
   2988 	old_cred = MPlayerCredits;
   2989 
   2990 	levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
   2991 	levelgauge.Set_Value(BuildLevel - 1);
   2992 
   2993 	countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
   2994 	countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
   2995 
   2996 	/*........................................................................
   2997 	Init other scenario parameters
   2998 	........................................................................*/
   2999 	Special.IsTGrowth = MPlayerTiberium;
   3000 	Special.IsTSpread = MPlayerTiberium;
   3001 	transmit = 0;
   3002 
   3003 	/*........................................................................
   3004 	Init scenario description list box
   3005 	........................................................................*/
   3006 	for (i = 0; i < MPlayerScenarios.Count(); i++) {
   3007 		scenariolist.Add_Item (strupr(MPlayerScenarios[i]));
   3008 	}
   3009 	ScenarioIdx = 0;								// 1st scenario is selected
   3010 
   3011 	/*........................................................................
   3012 	Init player color-used flags
   3013 	........................................................................*/
   3014 	for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
   3015 		ColorUsed[i] = 0;							// init all colors to available
   3016 	}
   3017 	ColorUsed[MPlayerColorIdx] = 1;			// set my color to used
   3018 	playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
   3019 
   3020 	/*........................................................................
   3021 	Init random-number generator, & create a seed to be used for all random
   3022 	numbers from here on out
   3023 	........................................................................*/
   3024 	//ST - 12/18/2018 11:37AM
   3025 	//randomize();
   3026 	//Seed = rand();
   3027 
   3028 	/*........................................................................
   3029 	Init the message display system
   3030 	........................................................................*/
   3031 	Messages.Init (d_message_x + 2*factor, d_message_y + 2*factor, 4, MAX_MESSAGE_LENGTH,
   3032 		d_txt6_h);
   3033 
   3034 	/*------------------------------------------------------------------------
   3035 	Add myself to the list.  Note that since I'm not in the Players Vector,
   3036 	the Vector & listbox are now 1 out of sync.
   3037 	------------------------------------------------------------------------*/
   3038 	item = new char [MPLAYER_NAME_MAX + 4];
   3039 	if (MPlayerHouse==HOUSE_GOOD) {
   3040 		sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
   3041 	} else {
   3042 		sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
   3043 	}
   3044 	playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
   3045 
   3046 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   3047 	Blit_Hid_Page_To_Seen_Buff();
   3048 	Set_Palette(Palette);
   3049 	while (Get_Mouse_State() > 0) Show_Mouse();
   3050 
   3051 	/*
   3052 	---------------------------- Processing loop -----------------------------
   3053 	*/
   3054 	while (process) {
   3055 
   3056 		/*
   3057 		** If we have just received input focus again after running in the background then
   3058 		** we need to redraw.
   3059 		*/
   3060 		if (AllSurfaces.SurfacesRestored){
   3061 			AllSurfaces.SurfacesRestored=FALSE;
   3062 			display=REDRAW_ALL;
   3063 		}
   3064 
   3065 		#if(SHOW_MONO)
   3066 		Ipx.Mono_Debug_Print(-1,0);
   3067 		#endif
   3068 		/*
   3069 		...................... Refresh display if needed ......................
   3070 		*/
   3071 		if (display == REDRAW_UNIT_COUNT){
   3072 			/*
   3073 			** Wipe the background behind the unit count then reprint it
   3074 			*/
   3075 			LogicPage->Fill_Rect(d_count_x + d_count_w + 2*factor,
   3076 										d_count_y,
   3077 										d_count_x + d_count_w + 2*factor + 20,
   3078 										d_count_y + 12,
   3079 										0 );
   3080 			sprintf(txt,"%d",MPlayerUnitCount);
   3081 			Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
   3082 									CC_GREEN, TBLACK,
   3083 									TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   3084 			display = REDRAW_NONE;
   3085 		}
   3086 
   3087 
   3088 		if (display) {
   3089 			Hide_Mouse();
   3090 			/*
   3091 			.................. Redraw backgound & dialog box ...................
   3092 			*/
   3093 			if (display >= REDRAW_BACKGROUND) {
   3094 
   3095 				/*
   3096 				** Reload and draw the title page
   3097 				*/
   3098 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   3099 				Blit_Hid_Page_To_Seen_Buff();
   3100 				Set_Palette(Palette);
   3101 
   3102 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
   3103 
   3104 				/*...............................................................
   3105 				Dialog & Field labels
   3106 				...............................................................*/
   3107 				Draw_Caption (TXT_NETGAME_SETUP, d_dialog_x, d_dialog_y, d_dialog_w);
   3108 
   3109 				Fancy_Text_Print(TXT_PLAYERS,
   3110 					d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
   3111 					CC_GREEN, TBLACK,
   3112 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
   3113 
   3114 				Fancy_Text_Print(TXT_SCENARIOS,
   3115 					d_scenariolist_x + (d_scenariolist_w / 2),
   3116 					d_scenariolist_y - d_txt6_h,
   3117 					CC_GREEN, TBLACK,
   3118 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
   3119 
   3120 				Fancy_Text_Print (TXT_COUNT, d_count_x - 2*factor, d_count_y,
   3121 					CC_GREEN, TBLACK,
   3122 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
   3123 
   3124 				sprintf(txt,"%d",MPlayerUnitCount);
   3125 				Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
   3126 					CC_GREEN, TBLACK,
   3127 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   3128 
   3129 				Fancy_Text_Print (TXT_LEVEL, d_level_x - 2*factor, d_level_y,
   3130 					CC_GREEN, TBLACK,
   3131 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
   3132 
   3133 				if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
   3134 					sprintf(txt,"%d",BuildLevel);
   3135 				} else {
   3136 					sprintf(txt, "**");
   3137 				}
   3138 				Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
   3139 					CC_GREEN, TBLACK,
   3140 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   3141 
   3142 				Fancy_Text_Print (TXT_START_CREDITS_COLON, d_credits_x - 5*factor,
   3143 					d_credits_y + 1*factor, CC_GREEN, TBLACK,
   3144 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
   3145 
   3146 			}
   3147 
   3148 			/*
   3149 			.......................... Redraw buttons ..........................
   3150 			*/
   3151 			if (display >= REDRAW_BUTTONS) {
   3152 				commands->Draw_All();
   3153 			}
   3154 
   3155 			/*..................................................................
   3156 			Draw the messages:
   3157 			- Erase an old message first
   3158 			- If we're in a game, print the game options (if they've been
   3159 			  received)
   3160 			- If we've been rejected from a game, print that message
   3161 			..................................................................*/
   3162 			if (display >= REDRAW_MESSAGE) {
   3163 				Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
   3164 					BOXSTYLE_GREEN_BORDER, true);
   3165 				Messages.Draw();
   3166 			}
   3167 
   3168 			Show_Mouse();
   3169 			display = REDRAW_NONE;
   3170 		}
   3171 
   3172 		/*
   3173 		........................... Get user input ............................
   3174 		*/
   3175 		input = commands->Input();
   3176 
   3177 		/*
   3178 		---------------------------- Process input ----------------------------
   3179 		*/
   3180 		switch (input) {
   3181 			/*------------------------------------------------------------------
   3182 			New Scenario selected.
   3183 			------------------------------------------------------------------*/
   3184 			case (BUTTON_SCENARIOLIST | KN_BUTTON):
   3185 				if (scenariolist.Current_Index() != ScenarioIdx) {
   3186 					ScenarioIdx = scenariolist.Current_Index();
   3187 					MPlayerCredits = atoi(credbuf);
   3188 					transmit = 1;
   3189 				}
   3190 				break;
   3191 
   3192 			/*------------------------------------------------------------------
   3193 			Reject the currently-selected player (don't allow rejecting myself,
   3194 			who will be the first entry in the list)
   3195 			------------------------------------------------------------------*/
   3196 			case (BUTTON_REJECT | KN_BUTTON):
   3197 				index = playerlist.Current_Index();
   3198 				if (index == 0) {
   3199 					CCMessageBox().Process (TXT_CANT_REJECT_SELF, TXT_OOPS);
   3200 					display = REDRAW_ALL;
   3201 					break;
   3202 				} else {
   3203 					if (index < 0 || index >= playerlist.Count()) {
   3204 						CCMessageBox().Process (TXT_SELECT_PLAYER_REJECT,TXT_OOPS);
   3205 						display = REDRAW_ALL;
   3206 						break;
   3207 					}
   3208 				}
   3209 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   3210 
   3211 				GPacket.Command = NET_REJECT_JOIN;
   3212 
   3213 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 1,
   3214 					&(Players[index - 1]->Address));
   3215 				break;
   3216 
   3217 			/*------------------------------------------------------------------
   3218 			User adjusts max # units
   3219 			------------------------------------------------------------------*/
   3220 			case (BUTTON_COUNT | KN_BUTTON):
   3221 				MPlayerUnitCount = countgauge.Get_Value() + MPlayerCountMin[MPlayerBases];
   3222 
   3223 				Hide_Mouse();
   3224 				LogicPage->Fill_Rect (d_count_x + d_count_w + 2*factor, d_count_y,
   3225 					d_count_x + d_count_w + 14*factor, d_count_y + 6*factor, BLACK);
   3226 
   3227 				sprintf(txt,"%d",MPlayerUnitCount);
   3228 				Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
   3229 					CC_GREEN, TBLACK,
   3230 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   3231 				Show_Mouse();
   3232 
   3233 				transmit = 1;
   3234 				break;
   3235 
   3236 			/*------------------------------------------------------------------
   3237 			User adjusts build level
   3238 			------------------------------------------------------------------*/
   3239 			case (BUTTON_LEVEL | KN_BUTTON):
   3240 				BuildLevel = levelgauge.Get_Value() + 1;
   3241 				if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX)	// if it's pegged, max it out
   3242 					BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
   3243 
   3244 				Hide_Mouse();
   3245 				LogicPage->Fill_Rect (d_level_x + d_level_w + 2*factor, d_level_y,
   3246 					d_level_x + d_level_w + 14*factor, d_level_y + 6*factor, BLACK);
   3247 
   3248 				if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
   3249 					sprintf(txt,"%d",BuildLevel);
   3250 				} else {
   3251 					sprintf(txt, "**");
   3252 				}
   3253 				Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
   3254 					CC_GREEN, TBLACK,
   3255 					TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
   3256 				Show_Mouse();
   3257 
   3258 				transmit = 1;
   3259 				break;
   3260 
   3261 			/*------------------------------------------------------------------
   3262 			User edits the credits value; retransmit new game options
   3263 			------------------------------------------------------------------*/
   3264 			case (BUTTON_CREDITS | KN_BUTTON):
   3265 				MPlayerCredits = atoi(credbuf);
   3266 				transmit = 1;
   3267 				break;
   3268 
   3269 			/*------------------------------------------------------------------
   3270 			Toggle bases:
   3271 			- Clear scenario list & rebuild it with new names
   3272 			- toggle bases button, change its text
   3273 			- adjust the MPlayerUnitCount to reflect the new allowed range,
   3274 			  using the current gauge setting
   3275 			- Change the unit count gauge limit & value
   3276 			------------------------------------------------------------------*/
   3277 			case (BUTTON_BASES | KN_BUTTON):
   3278 				if (MPlayerBases) {
   3279 					MPlayerBases = 0;
   3280 					basesbtn.Turn_Off();
   3281 					basesbtn.Set_Text(TXT_BASES_OFF);
   3282 					MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[0]-MPlayerCountMin[0],
   3283 						Cardinal_To_Fixed(MPlayerCountMax[1]-MPlayerCountMin[1],
   3284 						MPlayerUnitCount-MPlayerCountMin[1])) + MPlayerCountMin[0];
   3285 				} else {
   3286 					MPlayerBases = 1;
   3287 					basesbtn.Turn_On();
   3288 					basesbtn.Set_Text(TXT_BASES_ON);
   3289 					MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[1]-MPlayerCountMin[1],
   3290 						Cardinal_To_Fixed(MPlayerCountMax[0]-MPlayerCountMin[0],
   3291 						MPlayerUnitCount-MPlayerCountMin[0])) + MPlayerCountMin[1];
   3292 				}
   3293 				MPlayerCredits = atoi(credbuf);
   3294 				countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
   3295 				countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
   3296 				transmit = 1;
   3297 				countgauge.Flag_To_Redraw();
   3298 				display = REDRAW_UNIT_COUNT;
   3299 				break;
   3300 
   3301 			/*------------------------------------------------------------------
   3302 			Toggle tiberium
   3303 			------------------------------------------------------------------*/
   3304 			case (BUTTON_TIBERIUM | KN_BUTTON):
   3305 				if (MPlayerTiberium) {
   3306 					MPlayerTiberium = 0;
   3307 					Special.IsTGrowth = 0;
   3308 					Special.IsTSpread = 0;
   3309 					tiberiumbtn.Turn_Off();
   3310 					tiberiumbtn.Set_Text(TXT_TIBERIUM_OFF);
   3311 				} else {
   3312 					MPlayerTiberium = 1;
   3313 					Special.IsTGrowth = 1;
   3314 					Special.IsTSpread = 1;
   3315 					tiberiumbtn.Turn_On();
   3316 					tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
   3317 				}
   3318 				MPlayerCredits = atoi(credbuf);
   3319 				transmit = 1;
   3320 				break;
   3321 
   3322 			/*------------------------------------------------------------------
   3323 			Toggle goodies
   3324 			------------------------------------------------------------------*/
   3325 			case (BUTTON_GOODIES | KN_BUTTON):
   3326 				if (MPlayerGoodies) {
   3327 					MPlayerGoodies = 0;
   3328 					goodiesbtn.Turn_Off();
   3329 					goodiesbtn.Set_Text(TXT_CRATES_OFF);
   3330 				} else {
   3331 					MPlayerGoodies = 1;
   3332 					goodiesbtn.Turn_On();
   3333 					goodiesbtn.Set_Text(TXT_CRATES_ON);
   3334 				}
   3335 				MPlayerCredits = atoi(credbuf);
   3336 				transmit = 1;
   3337 				break;
   3338 
   3339 			/*------------------------------------------------------------------
   3340 			Toggle ghosts/capture-the-flag
   3341 			------------------------------------------------------------------*/
   3342 			case (BUTTON_GHOSTS | KN_BUTTON):
   3343 				if (!MPlayerGhosts && !Special.IsCaptureTheFlag) {	// ghosts OFF => ghosts ON
   3344 					MPlayerGhosts = 1;
   3345 					Special.IsCaptureTheFlag = 0;
   3346 					ghostsbtn.Turn_On();
   3347 					ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
   3348 				} else {
   3349 					if (MPlayerGhosts) {					// ghosts ON => capture-flag
   3350 						MPlayerGhosts = 0;
   3351 						Special.IsCaptureTheFlag = 1;
   3352 						ghostsbtn.Turn_On();
   3353 						ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
   3354 					} else {
   3355 						if (Special.IsCaptureTheFlag) {		// capture-flag => AI OFF
   3356 							MPlayerGhosts = 0;
   3357 							Special.IsCaptureTheFlag = 0;
   3358 							ghostsbtn.Turn_Off();
   3359 							ghostsbtn.Set_Text(TXT_AI_PLAYERS_OFF);
   3360 						}
   3361 					}
   3362 				}
   3363 
   3364 				MPlayerCredits = atoi(credbuf);
   3365 				transmit = 1;
   3366 				break;
   3367 
   3368 			/*------------------------------------------------------------------
   3369 			OK: exit loop with TRUE status
   3370 			------------------------------------------------------------------*/
   3371 			case (BUTTON_OK | KN_BUTTON):
   3372 				/*...............................................................
   3373 				If a new player has joined in the last second, don't allow
   3374 				an OK; force a wait longer than 1 second (to give all players
   3375 				a chance to know about this new guy)
   3376 				...............................................................*/
   3377 				i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)60);
   3378 				while (TickCount.Time() - ok_timer < i)
   3379 					Ipx.Service();
   3380 
   3381 				/*...............................................................
   3382 				If there are at least 2 players, go ahead & play; error otherwise
   3383 				...............................................................*/
   3384 				if (MPlayerSolo || Players.Count() > 0) {
   3385 					rc = TRUE;
   3386 					process = FALSE;
   3387 				} else {
   3388 					CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
   3389 					display = REDRAW_ALL;
   3390 				}
   3391 				break;
   3392 
   3393 			/*------------------------------------------------------------------
   3394 			CANCEL: send a SIGN_OFF, bail out with error code
   3395 			------------------------------------------------------------------*/
   3396 			case (KN_ESC):
   3397 				if (Messages.Get_Edit_Buf() != NULL) {
   3398 					Messages.Input(input);
   3399 					if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3400 					break;
   3401 				}
   3402 			case (BUTTON_CANCEL | KN_BUTTON):
   3403 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   3404 
   3405 				GPacket.Command = NET_SIGN_OFF;
   3406 				strcpy (GPacket.Name, MPlayerName);
   3407 
   3408 				/*...............................................................
   3409 				Broadcast my sign-off over my network
   3410 				...............................................................*/
   3411 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3412 					0, NULL);
   3413 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3414 					0, NULL);
   3415 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   3416 
   3417 				/*...............................................................
   3418 				Broadcast my sign-off over a bridged network if there is one
   3419 				...............................................................*/
   3420 				if (IsBridge) {
   3421 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   3422 						&BridgeNet);
   3423 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   3424 						&BridgeNet);
   3425 				}
   3426 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   3427 
   3428 				/*...............................................................
   3429 				And now, just be absolutely sure, send my sign-off to each
   3430 				player in my game.  (If there's a bridge between us, the other
   3431 				player will have specified my address, so he can cross the
   3432 				bridge; but I may not have specified a bridge address, so the
   3433 				only way I have of crossing the bridge is to send a packet
   3434 				directly to him.)
   3435 				...............................................................*/
   3436 				for (i = 0; i < Players.Count(); i++) {
   3437 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   3438 						&(Players[i]->Address));
   3439 					Ipx.Service();
   3440 				}
   3441 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   3442 				MPlayerGameName[0] = 0;
   3443 				process = false;
   3444 				rc = false;
   3445 				break;
   3446 
   3447 			/*------------------------------------------------------------------
   3448 			Default: manage the inter-player messages
   3449 			------------------------------------------------------------------*/
   3450 			default:
   3451 				/*...............................................................
   3452 				F4/SEND/'M' = send a message
   3453 				...............................................................*/
   3454 				if (Messages.Get_Edit_Buf()==NULL) {
   3455 					if (input == KN_M || input==(BUTTON_SEND | KN_BUTTON) ||
   3456 						input == KN_F4) {
   3457 						memset (txt, 0, 80);
   3458 
   3459 						strcpy(txt,Text_String(TXT_TO_ALL));	// "To All:"
   3460 
   3461 						Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
   3462 							TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
   3463 
   3464 						credit_edt.Clear_Focus();
   3465 						credit_edt.Flag_To_Redraw();
   3466 						if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3467 
   3468 						break;
   3469 					}
   3470 				} else {
   3471 
   3472 					/*...............................................................
   3473 					If we're already editing a message and the user clicks on
   3474 					'Send', translate our input to a Return so Messages.Input() will
   3475 					work properly.
   3476 					...............................................................*/
   3477 					if (input==(BUTTON_SEND | KN_BUTTON)) {
   3478 						input = KN_RETURN;
   3479 					}
   3480 				}
   3481 
   3482 				/*...............................................................
   3483 				Manage the message system (get rid of old messages)
   3484 				...............................................................*/
   3485 				if (Messages.Manage()) {
   3486 					if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3487 				}
   3488 
   3489 				/*...............................................................
   3490 				Re-draw the messages & service keyboard input for any message
   3491 				being edited.
   3492 				...............................................................*/
   3493 				i = Messages.Input(input);
   3494 
   3495 				/*...............................................................
   3496 				If 'Input' returned 1, it means refresh the message display.
   3497 				...............................................................*/
   3498 				if (i==1) {
   3499 					Messages.Draw();
   3500 				}
   3501 
   3502 				/*...............................................................
   3503 				If 'Input' returned 2, it means redraw the message display.
   3504 				...............................................................*/
   3505 				else if (i==2) {
   3506 					if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3507 				}
   3508 
   3509 				/*...............................................................
   3510 				If 'input' returned 3, it means send the current message.
   3511 				...............................................................*/
   3512 				else if (i==3) {
   3513 					long actual_message_size;
   3514 					char *the_string;
   3515 
   3516 					sent_so_far = 0;
   3517  					magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
   3518 					message_length = strlen(Messages.Get_Edit_Buf());
   3519 					crc = (unsigned short)
   3520 							(Calculate_CRC(Messages.Get_Edit_Buf(), message_length) &0xffff);
   3521 					while ( sent_so_far < message_length ){
   3522 						memset (&GPacket, 0, sizeof(GlobalPacketType));
   3523 						GPacket.Command = NET_MESSAGE;
   3524 						strcpy (GPacket.Name, MPlayerName);
   3525 						memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
   3526 
   3527 						/*
   3528 						** Steve I's stuff for splitting message on word boundries
   3529 						*/
   3530 						actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
   3531 
   3532 						/* Start at the end of the message and find a space with 10 chars. */
   3533 						the_string = GPacket.Message.Buf;
   3534 						while ( (COMPAT_MESSAGE_LENGTH -5) -actual_message_size < 10 &&
   3535 							the_string[actual_message_size] != ' '){
   3536 							--actual_message_size;
   3537 						}
   3538 						if ( the_string[actual_message_size] == ' ' ){
   3539 
   3540 							/* Now delete the extra characters after the space (they musnt print) */
   3541 							for ( int i=0 ; i< (COMPAT_MESSAGE_LENGTH-5) - actual_message_size; i++ ){
   3542 								the_string[i + actual_message_size] = 0;	//0xff; ST - 12/18/2018 11:37AM
   3543 							}
   3544 						}else{
   3545 							actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
   3546 						}
   3547 
   3548 						*(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
   3549 						*((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
   3550 						*((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
   3551 						GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   3552 						GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
   3553 
   3554 						/*..................................................................
   3555 						Send the message to every player in our player list.
   3556 						..................................................................*/
   3557 						for (i = 0; i < Players.Count(); i++) {
   3558 							Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   3559 								&(Players[i]->Address));
   3560 							Ipx.Service();
   3561 						}
   3562 						/*..................................................................
   3563 						Add the message to our own list, since we're not in the player list
   3564 						on this dialog.
   3565 						..................................................................*/
   3566 						sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
   3567 						Messages.Add_Message (txt, MPlayerTColors[MPlayerColorIdx],
   3568 							TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
   3569 
   3570 						magic_number++;
   3571 						sent_so_far += actual_message_size;	//COMPAT_MESSAGE_LENGTH-5;
   3572 
   3573 					}
   3574 					if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3575 				}
   3576 		}
   3577 
   3578 		/*---------------------------------------------------------------------
   3579 		Detect editing of the credits buffer, transmit new values to players
   3580 		---------------------------------------------------------------------*/
   3581 		if (atoi(credbuf) != old_cred) {
   3582 			old_cred = Bound(atoi(credbuf), 0, 9999);
   3583 			MPlayerCredits = old_cred;
   3584 			transmit = 1;
   3585 			sprintf(credbuf, "%d", MPlayerCredits);
   3586 			credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
   3587 		}
   3588 
   3589 		/*---------------------------------------------------------------------
   3590 		Process incoming packets
   3591 		---------------------------------------------------------------------*/
   3592 		whahoppa = Get_NewGame_Responses(&playerlist);
   3593 		if (whahoppa == EV_NEW_PLAYER) {
   3594 			ok_timer = TickCount.Time();
   3595 			transmit = 1;
   3596 		} else {
   3597 			if (whahoppa == EV_MESSAGE) {
   3598 				if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
   3599 			}
   3600 		}
   3601 
   3602 		/*---------------------------------------------------------------------
   3603 		If our Transmit flag is set, we need to send out a game option packet
   3604 		---------------------------------------------------------------------*/
   3605 		if (transmit) {
   3606 			for (i = 0; i < Players.Count(); i++) {
   3607 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   3608 
   3609 				GPacket.Command = NET_GAME_OPTIONS;
   3610 				GPacket.ScenarioInfo.Scenario = MPlayerFilenum[ScenarioIdx];
   3611 				GPacket.ScenarioInfo.Credits = MPlayerCredits;
   3612 				GPacket.ScenarioInfo.IsBases = MPlayerBases;
   3613 				GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
   3614 				GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
   3615 				GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
   3616 				GPacket.ScenarioInfo.BuildLevel = BuildLevel;
   3617 				GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
   3618 				GPacket.ScenarioInfo.Seed = Seed;
   3619 				GPacket.ScenarioInfo.Special = Special;
   3620 				GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
   3621 
   3622 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3623 					1, &(Players[i]->Address) );
   3624 			}
   3625 			transmit = 0;
   3626 		}
   3627 
   3628 		/*---------------------------------------------------------------------
   3629 		Ping every player in my game, to force the Global Channel to measure
   3630 		the connection response time.
   3631 		---------------------------------------------------------------------*/
   3632 		if (TickCount.Time() - ping_timer > 15) {
   3633 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   3634 			GPacket.Command = NET_PING;
   3635 			for (i = 0; i < Players.Count(); i++) {
   3636 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3637 					1, &(Players[i]->Address) );
   3638 			}
   3639 			ping_timer = TickCount.Time();
   3640 		}
   3641 
   3642 		/*---------------------------------------------------------------------
   3643 		Service the Ipx connections
   3644 		---------------------------------------------------------------------*/
   3645 		Ipx.Service();
   3646 
   3647 		/*---------------------------------------------------------------------
   3648 		Service the sounds & score; GameActive must be false at this point,
   3649 		so Call_Back() doesn't intercept global messages from me!
   3650 		---------------------------------------------------------------------*/
   3651 		Call_Back();
   3652 
   3653 	}	/* end of while */
   3654 
   3655 	/*------------------------------------------------------------------------
   3656 	Establish connections with all other players.
   3657 	------------------------------------------------------------------------*/
   3658 	if (rc) {
   3659 		/*.....................................................................
   3660 		Set the number of players in this game, and my ID
   3661 		.....................................................................*/
   3662 		MPlayerCount = Players.Count() + 1;
   3663 		MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   3664 
   3665 		/*.....................................................................
   3666 		Get the scenario filename
   3667 		.....................................................................*/
   3668 		Scenario = MPlayerFilenum[ScenarioIdx];
   3669 
   3670 		/*.....................................................................
   3671 		Compute frame delay value for packet transmissions:
   3672 		- Divide global channel's response time by 8 (2 to convert to 1-way
   3673 		  value, 4 more to convert from ticks to frames)
   3674 		.....................................................................*/
   3675 		MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), (unsigned long)2);
   3676 
   3677 		/*.....................................................................
   3678 		Send all players the NET_GO packet.  Wait until all ACK's have been
   3679 		received.
   3680 		.....................................................................*/
   3681 		memset (&GPacket, 0, sizeof(GlobalPacketType));
   3682 		GPacket.Command = NET_GO;
   3683 		GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
   3684 		for (i = 0; i < Players.Count(); i++) {
   3685 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3686 				1, &(Players[i]->Address) );
   3687 			/*..................................................................
   3688 			Wait for all the ACK's to come in.
   3689 			..................................................................*/
   3690 			while (Ipx.Global_Num_Send() > 0)
   3691 				Ipx.Service();
   3692 		}
   3693 
   3694 		/*.....................................................................
   3695 		Form connections with all other players.  Form the IPX Connection ID
   3696 		from the player's Color (high byte) and House (low byte).  This
   3697 		will let us extract any player's color & house at any time.
   3698 		Fill in 'tmp_id' while we're doing this.
   3699 		.....................................................................*/
   3700 		for (i = 0; i < Players.Count(); i++) {
   3701 			id = Build_MPlayerID (Players[i]->Player.Color,
   3702 				Players[i]->Player.House);
   3703 
   3704 			tmp_id[i] = id;
   3705 
   3706 			Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
   3707 		}
   3708 		tmp_id[i] = MPlayerLocalID;
   3709 
   3710 		/*.....................................................................
   3711 		Store every player's ID in the MPlayerID[] array.  This array will
   3712 		determine the order of event execution, so the ID's must be stored
   3713 		in the same order on all systems.
   3714 		.....................................................................*/
   3715 		for (i = 0; i < MPlayerCount; i++) {
   3716 			min_index = 0;
   3717 			min_id = 0xff;
   3718 			for (j = 0; j < MPlayerCount; j++) {
   3719 				if (tmp_id[j] < min_id) {
   3720 					min_id = tmp_id[j];
   3721 					min_index = j;
   3722 				}
   3723 			}
   3724 			MPlayerID[i] = tmp_id[min_index];
   3725 			tmp_id[min_index] = 0xff;
   3726 		}
   3727 		/*.....................................................................
   3728 		Fill in the array of player names, including my own.
   3729 		.....................................................................*/
   3730 		for (i = 0; i < MPlayerCount; i++) {
   3731 			if (MPlayerID[i] == MPlayerLocalID) {
   3732 				strcpy (MPlayerNames[i], MPlayerName);
   3733 			} else {
   3734 				strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
   3735 			}
   3736 		}
   3737 	}
   3738 
   3739 	/*------------------------------------------------------------------------
   3740 	Init network timing values, using previous response times as a measure
   3741 	of what our retry delta & timeout should be.
   3742 	------------------------------------------------------------------------*/
   3743 	Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
   3744 		Ipx.Global_Response_Time() * 4);
   3745 
   3746 	/*------------------------------------------------------------------------
   3747 	Clear all lists
   3748 	------------------------------------------------------------------------*/
   3749 	while (scenariolist.Count()) {
   3750 		scenariolist.Remove_Item(scenariolist.Get_Item(0));
   3751 	}
   3752 	Clear_Player_List(&playerlist);
   3753 
   3754 	/*------------------------------------------------------------------------
   3755 	Restore screen
   3756 	------------------------------------------------------------------------*/
   3757 	Hide_Mouse();
   3758 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   3759 	Blit_Hid_Page_To_Seen_Buff();
   3760 	Show_Mouse();
   3761 
   3762 	return(rc);
   3763 }
   3764 
   3765 
   3766 /***************************************************************************
   3767  * Get_NewGame_Responses -- processes packets for New Game dialog          *
   3768  *                                                                         *
   3769  * This routine can modify the contents of the given list box, as well		*
   3770  * as the contents of the Players Vector global.									*
   3771  *                                                                         *
   3772  * INPUT:                                                                  *
   3773  *		playerlist		list of players in this game									*
   3774  *                                                                         *
   3775  * OUTPUT:                                                                 *
   3776  *		EV_NONE = nothing happened															*
   3777  *		EV_NEW_PLAYER = a new player has joined; false otherwise					*
   3778  *		EV_MESSAGE = a message was received												*
   3779  *                                                                         *
   3780  * WARNINGS:                                                               *
   3781  *		none.																						*
   3782  *                                                                         *
   3783  * HISTORY:                                                                *
   3784  *   04/18/1995 BRR : Created.                                             *
   3785  *=========================================================================*/
   3786 static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist)
   3787 {
   3788 	int rc;
   3789 	char * item;						// general-purpose string
   3790 	NodeNameType *who;				// node to add to Players Vector
   3791 	int i;
   3792 	int found;
   3793 	JoinEventType retval = EV_NONE;
   3794 	int resend;
   3795 	char txt[80];
   3796 	int color;
   3797 	unsigned short magic_number;
   3798 	unsigned short crc;
   3799 
   3800 	/*------------------------------------------------------------------------
   3801 	If there is no incoming packet, just return
   3802 	------------------------------------------------------------------------*/
   3803 	rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
   3804 	if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER) {
   3805 		return(EV_NONE);
   3806 	}
   3807 
   3808 	/*------------------------------------------------------------------------
   3809 	Try to handle the packet in a standard way
   3810 	------------------------------------------------------------------------*/
   3811 	if (Process_Global_Packet(&GPacket,&GAddress) != 0) {
   3812 		return(EV_NONE);
   3813 	} else
   3814 
   3815 	/*------------------------------------------------------------------------
   3816 	NET_QUERY_JOIN:
   3817 	------------------------------------------------------------------------*/
   3818 	if (GPacket.Command==NET_QUERY_JOIN) {
   3819 		/*.....................................................................
   3820 		See if this name is unique:
   3821 		- If the name matches, but the address is different, reject this player
   3822 		- If the name & address match, this packet must be a re-send of a
   3823 		  prevous request; in this case, do nothing.  The other player must have
   3824 		  received my CONFIRM_JOIN packet (since it was sent with an ACK
   3825 		  required), so we can ignore this resend.
   3826 		.....................................................................*/
   3827 		found = 0;
   3828 		resend = 0;
   3829 		for (i = 0; i < Players.Count(); i++) {
   3830 			if (!strcmp(Players[i]->Name,GPacket.Name)) {
   3831 				if (Players[i]->Address != GAddress) {
   3832 					found = 1;
   3833 				}
   3834 				else {
   3835 					resend = 1;
   3836 				}
   3837 				break;
   3838 			}
   3839 		}
   3840 		if (!strcmp (MPlayerName, GPacket.Name)) {
   3841 			found = 1;
   3842 		}
   3843 
   3844 		/*.....................................................................
   3845 		Reject if name is a duplicate, or if there are too many players:
   3846 		.....................................................................*/
   3847 		if (found || (Players.Count() >= (MPlayerMax - 1) && !resend) ) {
   3848 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   3849 
   3850 			GPacket.Command = NET_REJECT_JOIN;
   3851 
   3852 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3853 				1, &GAddress);
   3854 		}
   3855 
   3856 		/*.....................................................................
   3857 		If this packet is NOT a resend, accept the player.  Grant him the
   3858 		requested color if possible.
   3859 		.....................................................................*/
   3860 		else if (!resend) {
   3861 			/*..................................................................
   3862 			Add node to the Vector list
   3863 			..................................................................*/
   3864 			who = new NodeNameType;
   3865 			strcpy(who->Name, GPacket.Name);
   3866 			who->Address = GAddress;
   3867 			who->Player.House = GPacket.PlayerInfo.House;
   3868 			Players.Add (who);
   3869 
   3870 			/*..................................................................
   3871 			Set player's color; if requested color isn't used, give it to him;
   3872 			otherwise, give him the 1st available color.  Mark the color we
   3873 			give him as used.
   3874 			..................................................................*/
   3875 			if (ColorUsed[GPacket.PlayerInfo.Color] == 0) {
   3876 				who->Player.Color = GPacket.PlayerInfo.Color;
   3877 			} else {
   3878 				for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
   3879 					if (ColorUsed[i]==0) {
   3880 						who->Player.Color = i;
   3881 						break;
   3882 					}
   3883 				}
   3884 			}
   3885 			ColorUsed[who->Player.Color] = 1;
   3886 
   3887 			/*..................................................................
   3888 			Add player name to the list box
   3889 			..................................................................*/
   3890 			item = new char [MPLAYER_NAME_MAX + 4];
   3891 			if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
   3892 				sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
   3893 			} else {
   3894 				sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
   3895 			}
   3896 			playerlist->Add_Item (item, MPlayerTColors[who->Player.Color]);
   3897 
   3898 			/*..................................................................
   3899 			Send a confirmation packet
   3900 			..................................................................*/
   3901 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   3902 
   3903 			GPacket.Command = NET_CONFIRM_JOIN;
   3904 			strcpy(GPacket.Name,MPlayerName);
   3905 			GPacket.PlayerInfo.House = who->Player.House;
   3906 			GPacket.PlayerInfo.Color = who->Player.Color;
   3907 
   3908 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   3909 				1, &GAddress);
   3910 
   3911 			retval = EV_NEW_PLAYER;
   3912 		}
   3913 	}
   3914 
   3915 	/*------------------------------------------------------------------------
   3916 	NET_SIGN_OFF: Another system is signing off: search for that system in
   3917 	the player list, & remove it if found
   3918 	------------------------------------------------------------------------*/
   3919 	else if (GPacket.Command==NET_SIGN_OFF) {
   3920 		for (i = 0; i < Players.Count(); i++) {
   3921 			/*
   3922 			....................... Name found; remove it ......................
   3923 			*/
   3924 			if (!strcmp (Players[i]->Name, GPacket.Name) &&
   3925 				Players[i]->Address==GAddress) {
   3926 				/*...............................................................
   3927 				Remove from the list box
   3928 				...............................................................*/
   3929 				item = (char *)(playerlist->Get_Item(i + 1));
   3930 				playerlist->Remove_Item(item);
   3931 				playerlist->Flag_To_Redraw();
   3932 				delete [] item;
   3933 				/*...............................................................
   3934 				Mark his color as available
   3935 				...............................................................*/
   3936 				ColorUsed[Players[i]->Player.Color] = 0;
   3937 				/*...............................................................
   3938 				Delete from the Vector list
   3939 				...............................................................*/
   3940 				Players.Delete(Players[i]);
   3941 				break;
   3942 			}
   3943 		}
   3944 	}
   3945 
   3946 	/*------------------------------------------------------------------------
   3947 	NET_MESSAGE: Someone is sending us a message
   3948 	------------------------------------------------------------------------*/
   3949 	else if (GPacket.Command==NET_MESSAGE) {
   3950 		sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
   3951 		magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
   3952 		crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
   3953 		color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
   3954 		Messages.Add_Message (txt, MPlayerTColors[color],
   3955 			TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
   3956 		retval = EV_MESSAGE;
   3957 	}
   3958 
   3959 	return(retval);
   3960 }
   3961 
   3962 
   3963 
   3964 /***************************************************************************
   3965  * Compute_Name_CRC -- computes CRC from char string                       *
   3966  *                                                                         *
   3967  * INPUT:                                                                  *
   3968  *		name		string to create CRC for												*
   3969  *                                                                         *
   3970  * OUTPUT:                                                                 *
   3971  *		CRC																						*
   3972  *                                                                         *
   3973  * WARNINGS:                                                               *
   3974  *		none.																						*
   3975  *                                                                         *
   3976  * HISTORY:                                                                *
   3977  *   06/29/1995 BRR : Created.                                             *
   3978  *=========================================================================*/
   3979 unsigned long Compute_Name_CRC(char *name)
   3980 {
   3981 	char buf[80];
   3982 	unsigned long crc = 0L;
   3983 	int i;
   3984 
   3985 	strcpy (buf, name);
   3986 	strupr (buf);
   3987 
   3988 	for (i = 0; i < (int)strlen(buf); i++) {
   3989 		Add_CRC (&crc, (unsigned long)buf[i]);
   3990 	}
   3991 
   3992 	return (crc);
   3993 }
   3994 
   3995 /***************************************************************************
   3996  * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog      *
   3997  *                                                                         *
   3998  * INPUT:                                                                  *
   3999  *		reconn			1 = reconnect, 0 = waiting for first-time connection	*
   4000  *		fresh				1 = draw from scratch, 0 = only update time counter	*
   4001  *		oldest_index	IPX connection index of oldest connection 				*
   4002  *							(only used for reconnection)									*
   4003  *		timeval			value to print in the countdown field						*
   4004  *                                                                         *
   4005  * OUTPUT:                                                                 *
   4006  *		none.																						*
   4007  *                                                                         *
   4008  * WARNINGS:                                                               *
   4009  *		none.																						*
   4010  *                                                                         *
   4011  * HISTORY:                                                                *
   4012  *   07/08/1995 BRR : Created.                                             *
   4013  *=========================================================================*/
   4014 void Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,
   4015 	unsigned long timeval)
   4016 {
   4017 	static int x,y,w,h;
   4018 	int id;
   4019 	char buf1[40] = {0};
   4020 	char buf2[40] = {0};
   4021 	char const *buf3 = "";
   4022 
   4023 	int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
   4024 
   4025 	int d_txt6_h = 6*factor+1;
   4026 	int d_margin = 5*factor;
   4027 
   4028 
   4029 	/*------------------------------------------------------------------------
   4030 	Draw the dialog from scratch
   4031 	------------------------------------------------------------------------*/
   4032 	if (fresh) {
   4033 		Fancy_Text_Print ("", 0, 0, CC_GREEN, TBLACK,
   4034 			TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4035 		if (reconn) {
   4036 			id = Ipx.Connection_ID(oldest_index);
   4037 			sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
   4038 				Ipx.Connection_Name(id));
   4039 		} else {
   4040 			sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
   4041 		}
   4042 		sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
   4043 		buf3 = Text_String(TXT_PRESS_ESC);
   4044 
   4045 		w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
   4046 		w = MAX(String_Pixel_Width(buf3), (unsigned)w);
   4047 		w += (d_margin * 4);
   4048 		h = (d_txt6_h * 3) + (d_margin * 6);
   4049 		x = 160*factor - (w / 2);
   4050 		y = 100*factor - (h / 2);
   4051 
   4052 		Hide_Mouse();
   4053 		Set_Logic_Page(SeenBuff);
   4054 		Dialog_Box(x, y, w, h);
   4055 
   4056 		Fancy_Text_Print (buf1, 160*factor, y + (d_margin * 2), CC_GREEN, BLACK,
   4057 			TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4058 
   4059 		Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
   4060 			CC_GREEN, BLACK,
   4061 			TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4062 
   4063 		Fancy_Text_Print (buf3, 160*factor, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2,
   4064 			CC_GREEN, BLACK,
   4065 			TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4066 
   4067 		Show_Mouse();
   4068 
   4069 	} else {
   4070 
   4071 		/*------------------------------------------------------------------------
   4072 		Just update the timeout value on the dialog
   4073 		------------------------------------------------------------------------*/
   4074 		Hide_Mouse();
   4075 		Set_Logic_Page(SeenBuff);
   4076 
   4077 		sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
   4078 		int pixwidth = String_Pixel_Width (buf2);
   4079 		LogicPage->Fill_Rect (160*factor - (pixwidth/2) - 12, y+(d_margin*2) + d_txt6_h + d_margin,
   4080 									160*factor + (pixwidth/2) + 12, y+(d_margin*2) + d_txt6_h*2 + d_margin,
   4081 									TBLACK);
   4082 		Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
   4083 			CC_GREEN, BLACK,
   4084 			TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4085 
   4086 		Show_Mouse();
   4087 	}
   4088 }
   4089 
   4090 
   4091 
   4092 
   4093 
   4094 
   4095 /***********************************************************************************************
   4096  * Wait_For_Focus -- Wait for game to be in focus before proceeding                            *
   4097  *                                                                                             *
   4098  *                                                                                             *
   4099  *                                                                                             *
   4100  * INPUT:    Nothing                                                                           *
   4101  *                                                                                             *
   4102  * OUTPUT:   Nothing                                                                           *
   4103  *                                                                                             *
   4104  * WARNINGS: None                                                                              *
   4105  *                                                                                             *
   4106  * HISTORY:                                                                                    *
   4107  *    1/6/97 3:23PM ST : Created                                                               *
   4108  *=============================================================================================*/
   4109 void Wait_For_Focus (void)
   4110 {
   4111 	CountDownTimerClass focus_timer;
   4112 	focus_timer.Set(5*60);
   4113 	ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
   4114 
   4115 	/*
   4116 	** Process the message loop until we are in focus.
   4117 	*/
   4118 	if (!GameInFocus){
   4119 		CCDebugString ("C&C95 - Waiting for game to come into focus.");
   4120 		do {
   4121 			CCDebugString (".");
   4122 			Keyboard::Check();
   4123 			if (!focus_timer.Time()){
   4124 				CCDebugString ("C&C95 - Calling SetForgroundWindow.\n");
   4125 				SetForegroundWindow ( MainWindow );
   4126 				CCDebugString ("C&C95 - Calling ShowWindow.\n");
   4127 				ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
   4128 				focus_timer.Set(5*60);
   4129 			}
   4130 
   4131 		}while (!GameInFocus);
   4132 		CCDebugString ("\n");
   4133 		AllSurfaces.SurfacesRestored=FALSE;
   4134 	}
   4135 }
   4136 
   4137 
   4138 
   4139 
   4140 
   4141 extern bool Spawn_WChat(bool can_launch);
   4142 
   4143 /***********************************************************************************************
   4144  * Net_Fake_New_Dialog -- Just like Net_New_Dialog but without the Dialog. For internet play   *
   4145  *                                                                                             *
   4146  *  This 'dialog' does all the non-dialog game set up stuff that is done in the normal         *
   4147  * network game set up dialog. The only visible button is 'cancel'                             *
   4148  *                                                                                             *
   4149  * INPUT:    Nothing                                                                           *
   4150  *                                                                                             *
   4151  * OUTPUT:   true if successfully connected                                                    *
   4152  *                                                                                             *
   4153  * WARNINGS: None                                                                              *
   4154  *                                                                                             *
   4155  * HISTORY:                                                                                    *
   4156  *    5/24/96 10:34AM ST : Created                                                             *
   4157  *=============================================================================================*/
   4158 static int Net_Fake_New_Dialog(void)
   4159 {
   4160 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
   4161 
   4162 	int d_dialog_w = 120*factor;											// dialog width
   4163 	int d_dialog_h = 80*factor;											// dialog height
   4164 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
   4165 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
   4166 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
   4167 
   4168 	//d_playerlist_w = 100;
   4169 	int d_playerlist_w = 106*factor;
   4170 	int d_playerlist_h = 27*factor;
   4171 	//int d_playerlist_x = 10 * factor;	//off screen
   4172 	int d_playerlist_x = 500*factor;	//10 * factor;	//off screen
   4173 	int d_playerlist_y = d_dialog_y + 20;
   4174 
   4175 #if (GERMAN | FRENCH)
   4176 	int d_cancel_w = 50*factor;
   4177 #else
   4178 	int d_cancel_w = 45*factor;
   4179 #endif
   4180 	int d_cancel_h = 9*factor;
   4181 	int d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
   4182 	int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
   4183 
   4184 #if (GERMAN | FRENCH)
   4185 	int	width=160*factor;
   4186 	int	height=80*factor;
   4187 #else
   4188 	int	width=120*factor;
   4189 	int	height=80*factor;
   4190 #endif	//GERMAN | FRENCH
   4191 
   4192 	bool	player_joined = false;
   4193 	CountDownTimerClass join_timer;
   4194 
   4195 	Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   4196 	Format_Window_String((char*)Text_String(TXT_CONNECTING), SeenBuff.Get_Height(), width, height);
   4197 
   4198 #if (GERMAN | FRENCH)
   4199 	d_dialog_w = width + 25*factor;
   4200 	d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
   4201 	d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
   4202 #endif
   4203 
   4204 
   4205 	/*........................................................................
   4206 	Button Enumerations
   4207 	........................................................................*/
   4208 	enum {
   4209 		BUTTON_CANCEL = 100,
   4210 		BUTTON_PLAYERLIST,
   4211 	};
   4212 
   4213 	/*........................................................................
   4214 	Redraw values: in order from "top" to "bottom" layer of the dialog
   4215 	........................................................................*/
   4216 	typedef enum {
   4217 		REDRAW_NONE = 0,
   4218 		REDRAW_MESSAGE,
   4219 		REDRAW_BUTTONS,
   4220 		REDRAW_BACKGROUND,
   4221 		REDRAW_ALL = REDRAW_BACKGROUND
   4222 	} RedrawType;
   4223 
   4224 	/*........................................................................
   4225 	Dialog variables
   4226 	........................................................................*/
   4227 	RedrawType display = REDRAW_ALL;		// redraw level
   4228 	bool process = true;						// process while true
   4229 	KeyNumType input;
   4230 
   4231 	char credbuf[CREDITSBUF_MAX];			// for credit edit box
   4232 	int old_cred;								// old value in credits buffer
   4233 	int transmit;								// 1 = re-transmit new game options
   4234 
   4235 	long ok_timer = 0;						// for timing OK button
   4236 	int rc;
   4237 	int i,j;
   4238 	char *item;
   4239 	int tabs[] = {77*factor};				// tabs for player list box
   4240 
   4241 	long ping_timer = 0;						// for sending Ping packets
   4242 
   4243 	unsigned char tmp_id[MAX_PLAYERS];	// temp storage for sorting player ID's
   4244 	int min_index;								// for sorting player ID's
   4245 	unsigned char min_id;					// for sorting player ID's
   4246 	unsigned char id;							// connection ID
   4247 	JoinEventType whahoppa;					// event generated by received packets
   4248 
   4249 	void const *up_button;
   4250 	void const *down_button;
   4251 
   4252 	if (InMainLoop){
   4253 		up_button = Hires_Retrieve("BTN-UP.SHP");
   4254 		down_button = Hires_Retrieve("BTN-DN.SHP");
   4255 	}else{
   4256 		up_button = Hires_Retrieve("BTN-UP2.SHP");
   4257 		down_button = Hires_Retrieve("BTN-DN2.SHP");
   4258 	}
   4259 
   4260 	/*........................................................................
   4261 	Buttons
   4262 	........................................................................*/
   4263 	GadgetClass *commands;										// button list
   4264 
   4265 	ColorListClass playerlist(BUTTON_PLAYERLIST,
   4266 		d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
   4267 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   4268 		up_button,
   4269 		down_button);
   4270 
   4271 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
   4272 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   4273 //#if (GERMAN | FRENCH)
   4274 //		d_cancel_x, d_cancel_y);
   4275 //#else
   4276 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
   4277 //#endif
   4278 
   4279 
   4280 	CCDebugString ("C&C95 - In new game dialog - initialising lists.\n");
   4281 	/*
   4282 	------------------------- Build the button list --------------------------
   4283 	*/
   4284 	commands = &playerlist;
   4285 	cancelbtn.Add_Tail(*commands);
   4286 
   4287 	playerlist.Set_Tabs(tabs);
   4288 
   4289 	/*
   4290 	----------------------------- Various Inits ------------------------------
   4291 	*/
   4292 
   4293 	sprintf(credbuf, "%d", MPlayerCredits);
   4294 	old_cred = MPlayerCredits;
   4295 
   4296 	/*........................................................................
   4297 	Init other scenario parameters
   4298 	........................................................................*/
   4299 	Special.IsTGrowth = MPlayerTiberium;
   4300 	Special.IsTSpread = MPlayerTiberium;
   4301 	transmit = 0;
   4302 
   4303 	/*........................................................................
   4304 	Init player color-used flags
   4305 	........................................................................*/
   4306 	for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
   4307 		ColorUsed[i] = 0;							// init all colors to available
   4308 	}
   4309 	ColorUsed[MPlayerColorIdx] = 1;			// set my color to used
   4310 	playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
   4311 
   4312 	/*........................................................................
   4313 	Init random-number generator, & create a seed to be used for all random
   4314 	numbers from here on out
   4315 	........................................................................*/
   4316 	//ST - 12/18/2018 11:37AM
   4317 	//randomize();
   4318 	//Seed = rand();
   4319 
   4320 	/*------------------------------------------------------------------------
   4321 	Add myself to the list.  Note that since I'm not in the Players Vector,
   4322 	the Vector & listbox are now 1 out of sync.
   4323 	------------------------------------------------------------------------*/
   4324 	item = new char [MPLAYER_NAME_MAX + 4];
   4325 	if (MPlayerHouse==HOUSE_GOOD) {
   4326 		sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
   4327 	} else {
   4328 		sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
   4329 	}
   4330 	playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
   4331 
   4332 	Wait_For_Focus();
   4333 
   4334 	CCDebugString ("C&C95 - About to uncompress title page.\n");
   4335 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   4336 	Blit_Hid_Page_To_Seen_Buff();
   4337 	CCDebugString ("C&C95 - About to set the palette.\n");
   4338 	Set_Palette(Palette);
   4339 	CCDebugString ("C&C95 - Palette was set OK.\n");
   4340 
   4341 	if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
   4342 		CCDebugString ("C&C95 - Logic page invalid");
   4343 		Set_Logic_Page (SeenBuff);
   4344 	}
   4345 
   4346 	char a_buffer [128];
   4347 	sprintf (a_buffer, "Number of players:%d", Players.Count());
   4348 	CCDebugString (a_buffer);
   4349 
   4350 
   4351 #ifdef VIRTUAL_SUBNET_SERVER
   4352 	/*
   4353 	** Send a bogus packet to wake up the VSS
   4354 	*/
   4355 	memset (&GPacket, 0, sizeof(GlobalPacketType));
   4356 
   4357 	GPacket.Command = (NetCommandType)50;		//Invalid command
   4358 	strcpy (GPacket.Name, MPlayerName);
   4359 	Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
   4360 #endif	//VIRTUAL_SUBNET_SERVER
   4361 
   4362 
   4363 	CCDebugString ("C&C95 - About to reveal mouse\n");
   4364 	while (Get_Mouse_State() > 0) Show_Mouse();
   4365 
   4366 	/*
   4367 	---------------------------- Processing loop -----------------------------
   4368 	*/
   4369 	CCDebugString ("C&C95 - Entering join dialogue loop\n");
   4370 	while (process) {
   4371 
   4372 		/*
   4373 		** If we have just received input focus again after running in the background then
   4374 		** we need to redraw.
   4375 		*/
   4376 		if (AllSurfaces.SurfacesRestored){
   4377 			AllSurfaces.SurfacesRestored=FALSE;
   4378 			display=REDRAW_ALL;
   4379 		}
   4380 
   4381 		/*
   4382 		...................... Refresh display if needed ......................
   4383 		*/
   4384 		if (display) {
   4385 			Hide_Mouse();
   4386 			/*
   4387 			.................. Redraw backgound & dialog box ...................
   4388 			*/
   4389 			if (display >= REDRAW_BACKGROUND) {
   4390 
   4391 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   4392 				Blit_Hid_Page_To_Seen_Buff();
   4393 				Set_Palette(Palette);
   4394 
   4395 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
   4396 
   4397 				/*...............................................................
   4398 				Dialog & Field labels
   4399 				...............................................................*/
   4400 				Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
   4401 
   4402 				Fancy_Text_Print(TXT_CONNECTING, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
   4403 									TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4404 			}
   4405 
   4406 			/*
   4407 			.......................... Redraw buttons ..........................
   4408 			*/
   4409 			if (display >= REDRAW_BUTTONS) {
   4410 				commands->Draw_All();
   4411 			}
   4412 
   4413 			Show_Mouse();
   4414 			display = REDRAW_NONE;
   4415 		}
   4416 
   4417 		/*
   4418 		........................... Get user input ............................
   4419 		*/
   4420 		input = commands->Input();
   4421 
   4422 		/*
   4423 		---------------------------- Process input ----------------------------
   4424 		*/
   4425 		switch (input) {
   4426 
   4427 			/*------------------------------------------------------------------
   4428 			CANCEL: send a SIGN_OFF, bail out with error code
   4429 			------------------------------------------------------------------*/
   4430 			case (KN_ESC):
   4431 			case (BUTTON_CANCEL | KN_BUTTON):
   4432 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   4433 
   4434 				GPacket.Command = NET_SIGN_OFF;
   4435 				strcpy (GPacket.Name, MPlayerName);
   4436 
   4437 				/*...............................................................
   4438 				Broadcast my sign-off over my network
   4439 				...............................................................*/
   4440 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   4441 					0, NULL);
   4442 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   4443 					0, NULL);
   4444 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   4445 
   4446 				/*...............................................................
   4447 				Broadcast my sign-off over a bridged network if there is one
   4448 				...............................................................*/
   4449 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   4450 
   4451 				/*...............................................................
   4452 				And now, just be absolutely sure, send my sign-off to each
   4453 				player in my game.  (If there's a bridge between us, the other
   4454 				player will have specified my address, so he can cross the
   4455 				bridge; but I may not have specified a bridge address, so the
   4456 				only way I have of crossing the bridge is to send a packet
   4457 				directly to him.)
   4458 				...............................................................*/
   4459 				for (i = 0; i < Players.Count(); i++) {
   4460 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   4461 						&(Players[i]->Address));
   4462 					Ipx.Service();
   4463 				}
   4464 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   4465 				MPlayerGameName[0] = 0;
   4466 				process = false;
   4467 				rc = false;
   4468 				Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
   4469 				GameStatisticsPacketSent = false;
   4470 				Spawn_WChat(false);
   4471 				break;
   4472 
   4473 			/*------------------------------------------------------------------
   4474 			default: exit loop with TRUE status
   4475 			------------------------------------------------------------------*/
   4476 			default:
   4477 #ifdef VIRTUAL_SUBNET_SERVER
   4478 				if (Players.Count() == InternetMaxPlayers-1){
   4479 
   4480 
   4481 #else //VIRTUAL_SUBNET_SERVER
   4482 				if (Players.Count() > 0){
   4483 #endif	// VIRTUAL_SUBNET_SERVER
   4484 
   4485 //char ddkks[128];
   4486 //sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
   4487 //CCDebugString (ddkks);
   4488 
   4489 					/*
   4490 					** Wait for several secs after receiving request to join before sending
   4491 					** start game packet
   4492 					*/
   4493 					if (!player_joined){
   4494 						player_joined = true;
   4495 						join_timer.Set (3*60, true);
   4496 						break;
   4497 					}else{
   4498 						if (join_timer.Time()) break;
   4499 					}
   4500 
   4501 CCDebugString ("C&C95 - Join timer expired\n");
   4502 
   4503 					/*...............................................................
   4504 					If a new player has joined in the last second, don't allow
   4505 					an OK; force a wait longer than 2 seconds (to give all players
   4506 					a chance to know about this new guy)
   4507 					...............................................................*/
   4508 					i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)120);
   4509 					while (TickCount.Time() - ok_timer < i)
   4510 						Ipx.Service();
   4511 
   4512 					/*...............................................................
   4513 					If there are at least 2 players, go ahead & play; error otherwise
   4514 					...............................................................*/
   4515 					if (MPlayerSolo || Players.Count() > 0) {
   4516 						rc = TRUE;
   4517 						process = FALSE;
   4518 					} else {
   4519 						CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
   4520 						display = REDRAW_ALL;
   4521 					}
   4522 				}
   4523 				break;
   4524 		}
   4525 
   4526 		/*---------------------------------------------------------------------
   4527 		Process incoming packets
   4528 		---------------------------------------------------------------------*/
   4529 		whahoppa = Get_NewGame_Responses(&playerlist);
   4530 		if (whahoppa == EV_NEW_PLAYER) {
   4531 			ok_timer = TickCount.Time();
   4532 			transmit = 1;
   4533 		} else {
   4534 			if (whahoppa == EV_MESSAGE) {
   4535 				display = REDRAW_MESSAGE;
   4536 			}
   4537 		}
   4538 
   4539 		/*---------------------------------------------------------------------
   4540 		If our Transmit flag is set, we need to send out a game option packet
   4541 		---------------------------------------------------------------------*/
   4542 		if (transmit) {
   4543 			for (i = 0; i < Players.Count(); i++) {
   4544 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   4545 
   4546 				GPacket.Command = NET_GAME_OPTIONS;
   4547 				GPacket.ScenarioInfo.Scenario = ScenarioIdx;	//MPlayerFilenum[ScenarioIdx];
   4548 				GPacket.ScenarioInfo.Credits = MPlayerCredits;
   4549 				GPacket.ScenarioInfo.IsBases = MPlayerBases;
   4550 				GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
   4551 				GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
   4552 				GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
   4553 				GPacket.ScenarioInfo.BuildLevel = BuildLevel;
   4554 				GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
   4555 				GPacket.ScenarioInfo.Seed = Seed;
   4556 				GPacket.ScenarioInfo.Special = Special;
   4557 				GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
   4558 
   4559 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   4560 					1, &(Players[i]->Address) );
   4561 			}
   4562 			transmit = 0;
   4563 		}
   4564 
   4565 		/*---------------------------------------------------------------------
   4566 		Ping every player in my game, to force the Global Channel to measure
   4567 		the connection response time.
   4568 		---------------------------------------------------------------------*/
   4569 		if (TickCount.Time() - ping_timer > 15) {
   4570 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   4571 			GPacket.Command = NET_PING;
   4572 			for (i = 0; i < Players.Count(); i++) {
   4573 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   4574 					1, &(Players[i]->Address) );
   4575 			}
   4576 			ping_timer = TickCount.Time();
   4577 		}
   4578 
   4579 		/*---------------------------------------------------------------------
   4580 		Service the Ipx connections
   4581 		---------------------------------------------------------------------*/
   4582 		Ipx.Service();
   4583 
   4584 		/*---------------------------------------------------------------------
   4585 		Service the sounds & score; GameActive must be false at this point,
   4586 		so Call_Back() doesn't intercept global messages from me!
   4587 		---------------------------------------------------------------------*/
   4588 		Call_Back();
   4589 
   4590 	}	/* end of while */
   4591 
   4592 CCDebugString ("C&C95 - Exited process loop\n");
   4593 
   4594 	/*------------------------------------------------------------------------
   4595 	Establish connections with all other players.
   4596 	------------------------------------------------------------------------*/
   4597 	if (rc) {
   4598 		/*.....................................................................
   4599 		Set the number of players in this game, and my ID
   4600 		.....................................................................*/
   4601 		MPlayerCount = Players.Count() + 1;
   4602 		MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   4603 
   4604 		/*.....................................................................
   4605 		Get the scenario filename
   4606 		.....................................................................*/
   4607 		Scenario = ScenarioIdx;	//PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
   4608 		//Scenario = MPlayerFilenum[ScenarioIdx];
   4609 
   4610 		/*.....................................................................
   4611 		Compute frame delay value for packet transmissions:
   4612 		- Divide global channel's response time by 8 (2 to convert to 1-way
   4613 		  value, 4 more to convert from ticks to frames)
   4614 		.....................................................................*/
   4615 		MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), (unsigned long)2);
   4616 
   4617 		/*.....................................................................
   4618 		Send all players the NET_GO packet.  Wait until all ACK's have been
   4619 		received.
   4620 		.....................................................................*/
   4621 CCDebugString ("C&C95 - Sending the 'GO' packet\n");
   4622 		memset (&GPacket, 0, sizeof(GlobalPacketType));
   4623 		GPacket.Command = NET_GO;
   4624 		GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
   4625 		for (i = 0; i < Players.Count(); i++) {
   4626 char flopbuf [128];
   4627 sprintf (flopbuf, "Sending 'GO' packet to address %d\n", *((unsigned short*)&(Players[i]->Address)));
   4628 CCDebugString (flopbuf);
   4629 
   4630 
   4631 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   4632 				1, &(Players[i]->Address) );
   4633 			/*..................................................................
   4634 			Wait for all the ACK's to come in.
   4635 			..................................................................*/
   4636 			while (Ipx.Global_Num_Send() > 0)
   4637 				Ipx.Service();
   4638 		}
   4639 
   4640 		/*.....................................................................
   4641 		Form connections with all other players.  Form the IPX Connection ID
   4642 		from the player's Color (high byte) and House (low byte).  This
   4643 		will let us extract any player's color & house at any time.
   4644 		Fill in 'tmp_id' while we're doing this.
   4645 		.....................................................................*/
   4646 		for (i = 0; i < Players.Count(); i++) {
   4647 			id = Build_MPlayerID (Players[i]->Player.Color,
   4648 				Players[i]->Player.House);
   4649 
   4650 			tmp_id[i] = id;
   4651 
   4652 			Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
   4653 		}
   4654 
   4655 #ifdef VIRTUAL_SUBNET_SERVER
   4656 CCDebugString ("C&C95 - Creating connection to the VSS\n");
   4657 		/*
   4658 		** Create an additional connection to the VSS
   4659 		*/
   4660 		if (UseVirtualSubnetServer){
   4661 			IPXAddressClass vss_global_address;
   4662 			NetNodeType vss_node;
   4663 			NetNumType	vss_net;
   4664 			memset (vss_net, 1, sizeof (vss_net));
   4665 			memset (vss_node, 0, sizeof (vss_node));
   4666 			vss_global_address.Set_Address(vss_net, vss_node);
   4667 			Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
   4668 		}
   4669 #endif	//VIRTUAL_SUBNET_SERVER
   4670 		tmp_id[i] = MPlayerLocalID;
   4671 
   4672 		/*.....................................................................
   4673 		Store every player's ID in the MPlayerID[] array.  This array will
   4674 		determine the order of event execution, so the ID's must be stored
   4675 		in the same order on all systems.
   4676 		.....................................................................*/
   4677 		for (i = 0; i < MPlayerCount; i++) {
   4678 			min_index = 0;
   4679 			min_id = 0xff;
   4680 			for (j = 0; j < MPlayerCount; j++) {
   4681 				if (tmp_id[j] < min_id) {
   4682 					min_id = tmp_id[j];
   4683 					min_index = j;
   4684 				}
   4685 			}
   4686 			MPlayerID[i] = tmp_id[min_index];
   4687 			tmp_id[min_index] = 0xff;
   4688 		}
   4689 		/*.....................................................................
   4690 		Fill in the array of player names, including my own.
   4691 		.....................................................................*/
   4692 		for (i = 0; i < MPlayerCount; i++) {
   4693 			if (MPlayerID[i] == MPlayerLocalID) {
   4694 				strcpy (MPlayerNames[i], MPlayerName);
   4695 			} else {
   4696 				strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
   4697 			}
   4698 		}
   4699 	}
   4700 
   4701 	/*------------------------------------------------------------------------
   4702 	Init network timing values, using previous response times as a measure
   4703 	of what our retry delta & timeout should be.
   4704 	------------------------------------------------------------------------*/
   4705 	Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
   4706 		Ipx.Global_Response_Time() * 4);
   4707 
   4708 	/*------------------------------------------------------------------------
   4709 	Clear all lists
   4710 	------------------------------------------------------------------------*/
   4711 	Clear_Player_List(&playerlist);
   4712 
   4713 	/*------------------------------------------------------------------------
   4714 	Restore screen
   4715 	------------------------------------------------------------------------*/
   4716 	Hide_Mouse();
   4717 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   4718 	Blit_Hid_Page_To_Seen_Buff();
   4719 	Show_Mouse();
   4720 
   4721 	if (rc){
   4722 		Wait_For_Focus();
   4723 	}
   4724 
   4725 	return(rc);
   4726 }
   4727 
   4728 
   4729 
   4730 
   4731 
   4732 
   4733 /***********************************************************************************************
   4734  * Net_Fake_Join_Dialog -- Like Net_Join_Dialog but with no dialogs. For Internet Play.        *
   4735  *                                                                                             *
   4736  *  This 'dialog' does all the non-dialog game set up stuff that is done in the normal         *
   4737  * network game set up dialog. The only visible button is 'cancel'                             *
   4738  *                                                                                             *
   4739  *                                                                                             *
   4740  * INPUT:    Nothing                                                                           *
   4741  *                                                                                             *
   4742  * OUTPUT:   0 = good, -1 = bad                                                                *
   4743  *                                                                                             *
   4744  * WARNINGS: None                                                                              *
   4745  *                                                                                             *
   4746  * HISTORY:                                                                                    *
   4747  *    5/24/96 11:07AM ST : Created                                                             *
   4748  *=============================================================================================*/
   4749 
   4750 static int Net_Fake_Join_Dialog(void)
   4751 {
   4752 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
   4753 	/*........................................................................
   4754 	Dialog & button dimensions
   4755 	........................................................................*/
   4756 /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
   4757 	int d_dialog_w = 120 *factor;											// dialog width
   4758 	int d_dialog_h = 80*factor;											// dialog height
   4759 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
   4760 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
   4761 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
   4762 
   4763 	int d_margin1=10;
   4764 	int d_txt6_h=15;
   4765 
   4766 	int d_gamelist_w = 160*factor;
   4767 	int d_gamelist_h = 27*factor;
   4768 	int d_gamelist_x = 500*factor;  //230*factor;	//Off screen
   4769 	//int d_gamelist_x = 230*factor;	//Off screen
   4770 	int d_gamelist_y = d_dialog_y + 20;
   4771 
   4772 	int d_playerlist_w = 106*factor;
   4773 	int d_playerlist_h = 27*factor;
   4774 	//int d_playerlist_x = 10 * factor;	//Off screen
   4775 	int d_playerlist_x = 500*factor;	//10 * factor;	//Off screen
   4776 	int d_playerlist_y = d_gamelist_y + 20;
   4777 
   4778 #if (GERMAN | FRENCH)
   4779 	int d_cancel_w = 50*factor;
   4780 #else
   4781 	int d_cancel_w = 45*factor;
   4782 #endif
   4783 	int d_cancel_h = 9*factor;
   4784 	int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
   4785 	int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
   4786 
   4787 	bool ready_to_go = false;
   4788 
   4789 #if (GERMAN | FRENCH)
   4790 	int	width=160*factor;
   4791 	int	height=80*factor;
   4792 #else
   4793 	int	width=120*factor;
   4794 	int	height=80*factor;
   4795 #endif	//GERMAN | FRENCH
   4796 
   4797 	Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
   4798 	Format_Window_String((char*)Text_String(TXT_CONNECTING), SeenBuff.Get_Height(), width, height);
   4799 
   4800 #if (GERMAN | FRENCH)
   4801 	d_dialog_w = width + 25*factor;
   4802 	d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
   4803 	d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
   4804 #endif
   4805 
   4806 	/*........................................................................
   4807 	Button Enumerations
   4808 	........................................................................*/
   4809 	enum {
   4810 		BUTTON_CANCEL = 100,
   4811 		BUTTON_GAMELIST,
   4812 		BUTTON_PLAYERLIST,
   4813 	};
   4814 
   4815 	/*........................................................................
   4816 	Redraw values: in order from "top" to "bottom" layer of the dialog
   4817 	........................................................................*/
   4818 	typedef enum {
   4819 		REDRAW_NONE = 0,
   4820 		REDRAW_MESSAGE,
   4821 		REDRAW_COLORS,
   4822 		REDRAW_BUTTONS,
   4823 		REDRAW_BACKGROUND,
   4824 		REDRAW_ALL = REDRAW_BACKGROUND
   4825 	} RedrawType;
   4826 
   4827 	/*........................................................................
   4828 	Dialog variables
   4829 	........................................................................*/
   4830 	RedrawType display = REDRAW_ALL;		// redraw level
   4831 	bool process = true;						// process while true
   4832 	KeyNumType input;
   4833 
   4834 	JoinStateType joinstate = JOIN_NOTHING;	// current "state" of this dialog
   4835 	char namebuf[MPLAYER_NAME_MAX] = {0};		// buffer for player's name
   4836 	int game_index = -1;						// index of currently-selected game
   4837 	int join_index = -1;						// index of game we're joining
   4838 	int rc = 0;									// -1 = user cancelled, 1 = New
   4839 	JoinEventType event;						// event from incoming packet
   4840 	int i,j;										// loop counter
   4841 	int parms_received;						// 1 = game options received
   4842 
   4843 	unsigned char tmp_id[MAX_PLAYERS];	// temp storage for sorting player ID's
   4844 	int min_index;								// for sorting player ID's
   4845 	unsigned char min_id;					// for sorting player ID's
   4846 	unsigned char id;							// connection ID
   4847 	char * item;
   4848 	unsigned long starttime;
   4849 
   4850 	NodeNameType *who;
   4851 
   4852 	void const *up_button;
   4853 	void const *down_button;
   4854 
   4855 	if (InMainLoop){
   4856 		up_button = Hires_Retrieve("BTN-UP.SHP");
   4857 		down_button = Hires_Retrieve("BTN-DN.SHP");
   4858 	}else{
   4859 		up_button = Hires_Retrieve("BTN-UP2.SHP");
   4860 		down_button = Hires_Retrieve("BTN-DN2.SHP");
   4861 	}
   4862 
   4863 	/*........................................................................
   4864 	Buttons
   4865 	........................................................................*/
   4866 	GadgetClass *commands;										// button list
   4867 
   4868 	ColorListClass playerlist(BUTTON_PLAYERLIST,
   4869 		d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
   4870 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   4871 		up_button,
   4872 		down_button);
   4873 
   4874 	ListClass gamelist(BUTTON_GAMELIST,
   4875 		d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
   4876 		TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   4877 		up_button,
   4878 		down_button);
   4879 
   4880 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
   4881 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
   4882 //#if (GERMAN | FRENCH)
   4883 //		d_cancel_x, d_cancel_y);
   4884 //#else
   4885 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
   4886 //#endif
   4887 
   4888 	/*
   4889 	----------------------------- Various Inits ------------------------------
   4890 	*/
   4891 	//MPlayerColorIdx = MPlayerPrefColor;			// init my preferred color
   4892 
   4893 	playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
   4894 
   4895 	Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
   4896 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4897 
   4898 	/*
   4899 	--------------------------- Send network query ---------------------------
   4900 	*/
   4901 	CCDebugString ("C&C95 - About to call Send_Join_Queries.\n");
   4902 	Send_Join_Queries (game_index, 1, 0);
   4903 
   4904 	Wait_For_Focus();
   4905 
   4906 	CCDebugString ("C&C95 - About to uncompress title page.\n");
   4907 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   4908 	Blit_Hid_Page_To_Seen_Buff();
   4909 	CCDebugString ("C&C95 - About to set the palette.\n");
   4910 	Set_Palette(Palette);
   4911 	CCDebugString ("C&C95 - Palette was set OK.\n");
   4912 
   4913 	if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
   4914 		CCDebugString ("C&C95 - Logic page invalid\n");
   4915 		Set_Logic_Page (SeenBuff);
   4916 	}
   4917 
   4918 
   4919 	char a_buffer [128];
   4920 	sprintf (a_buffer, "C&C95 - Number of players:%d\n", Players.Count());
   4921 	CCDebugString (a_buffer);
   4922 
   4923 	/*
   4924 	---------------------------- Init Mono Output ----------------------------
   4925 	*/
   4926 	CCDebugString ("C&C95 - About to reveal mouse\n");
   4927 	while (Get_Mouse_State() > 0) Show_Mouse();
   4928 
   4929 	/*
   4930 	---------------------------- Processing loop -----------------------------
   4931 	*/
   4932 	CCDebugString ("C&C95 - Entering join dialogue loop\n");
   4933 	while (process) {
   4934 
   4935 		/*
   4936 		** If we have just received input focus again after running in the background then
   4937 		** we need to redraw.
   4938 		*/
   4939 		if (AllSurfaces.SurfacesRestored){
   4940 			AllSurfaces.SurfacesRestored=FALSE;
   4941 			display=REDRAW_ALL;
   4942 		}
   4943 
   4944 		/*
   4945 		...................... Refresh display if needed ......................
   4946 		*/
   4947 		if (display) {
   4948 			Hide_Mouse();
   4949 			/*
   4950 			.................. Redraw backgound & dialog box ...................
   4951 			*/
   4952 			if (display >= REDRAW_BACKGROUND) {
   4953 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   4954 				Blit_Hid_Page_To_Seen_Buff();
   4955 				Set_Palette(Palette);
   4956 
   4957 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
   4958 
   4959 				/*...............................................................
   4960 				Dialog & Field labels
   4961 				...............................................................*/
   4962 				Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
   4963 
   4964 				Fancy_Text_Print(TXT_CONNECTING, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
   4965 									TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
   4966 
   4967 				/*
   4968 				.................... Rebuild the button list ....................
   4969 				*/
   4970 				cancelbtn.Zap();
   4971 				gamelist.Zap();
   4972 				playerlist.Zap();
   4973 
   4974 				commands = &cancelbtn;
   4975 				gamelist.Add_Tail(*commands);
   4976 				playerlist.Add_Tail(*commands);
   4977 			}
   4978 			/*
   4979 			.......................... Redraw buttons ..........................
   4980 			*/
   4981 			if (display >= REDRAW_BUTTONS) {
   4982 				commands->Draw_All();
   4983 			}
   4984 
   4985 			Show_Mouse();
   4986 			display = REDRAW_NONE;
   4987 		}
   4988 
   4989 		/*
   4990 		........................... Get user input ............................
   4991 		*/
   4992 		input = commands->Input();
   4993 
   4994 		/*
   4995 		---------------------------- Process input ----------------------------
   4996 		*/
   4997 		switch (input) {
   4998 
   4999 			/*------------------------------------------------------------------
   5000 			CANCEL: send a SIGN_OFF
   5001 			- If we're part of a game, stay in this dialog; otherwise, exit
   5002 			------------------------------------------------------------------*/
   5003 			case (KN_ESC):
   5004 			case (BUTTON_CANCEL | KN_BUTTON):
   5005 				memset (&GPacket, 0, sizeof(GlobalPacketType));
   5006 
   5007 				GPacket.Command = NET_SIGN_OFF;
   5008 				strcpy(GPacket.Name,MPlayerName);
   5009 
   5010 				/*...............................................................
   5011 				If we're joined to a game, make extra sure the other players in
   5012 				that game know I'm exiting; send my SIGN_OFF as an ack-required
   5013 				packet.  Do not send this packet to myself (index 0).
   5014 				...............................................................*/
   5015 				if (joinstate == JOIN_CONFIRMED) {
   5016 					//
   5017 					// Remove myself from the player list box
   5018 					//
   5019 					item = (char *)(playerlist.Get_Item(0));
   5020 					playerlist.Remove_Item(item);
   5021 					delete [] item;
   5022 					playerlist.Flag_To_Redraw();
   5023 
   5024 					//
   5025 					// Remove myself from the Players list
   5026 					//
   5027 					who = Players[0];
   5028 					Players.Delete(0);
   5029 					delete who;
   5030 
   5031 					for (i = 0; i < Players.Count(); i++) {
   5032 						Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   5033 							&(Players[i]->Address));
   5034 						Ipx.Service();
   5035 					}
   5036 				}
   5037 
   5038 				/*...............................................................
   5039 				Now broadcast my SIGN_OFF so other players looking at this game
   5040 				know I'm leaving.
   5041 				...............................................................*/
   5042 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   5043 					0, NULL);
   5044 				Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   5045 					0, NULL);
   5046 
   5047 				if (IsBridge) {
   5048 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   5049 						&BridgeNet);
   5050 					Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   5051 						&BridgeNet);
   5052 				}
   5053 
   5054 				while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   5055 
   5056 				Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
   5057 				GameStatisticsPacketSent = false;
   5058 				Spawn_WChat(false);
   5059 				process = false;
   5060 				rc = -1;
   5061 #if (0)
   5062 				if (joinstate != JOIN_CONFIRMED) {
   5063 					process = false;
   5064 					rc = -1;
   5065 				} else {
   5066 					MPlayerGameName[0] = 0;
   5067 					joinstate = JOIN_NOTHING;
   5068 					display = REDRAW_ALL;
   5069 				}
   5070 #endif	//(0)
   5071 				break;
   5072 
   5073 			/*------------------------------------------------------------------
   5074 			JOIN: send a join request packet & switch to waiting-for-confirmation
   5075 			mode.  (Request_To_Join fills in MPlayerName with my namebuf.)
   5076 			------------------------------------------------------------------*/
   5077 			default:
   5078 				if (joinstate == JOIN_NOTHING && Games.Count()!=0){
   5079 					gamelist.Set_Selected_Index(0);
   5080 					join_index = gamelist.Current_Index();
   5081 					parms_received = 0;
   5082 					if (Request_To_Join (MPlayerName, join_index, &playerlist, MPlayerHouse,
   5083 						MPlayerColorIdx)) {
   5084 						joinstate = JOIN_WAIT_CONFIRM;
   5085 					} else {
   5086 						display = REDRAW_ALL;
   5087 					}
   5088 				}
   5089 				break;
   5090 
   5091 		}
   5092 
   5093 		/*---------------------------------------------------------------------
   5094 		Resend our query packets
   5095 		---------------------------------------------------------------------*/
   5096 		Send_Join_Queries(game_index, 0, 0);
   5097 
   5098 		/*---------------------------------------------------------------------
   5099 		Process incoming packets
   5100 		---------------------------------------------------------------------*/
   5101 		event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
   5102 			join_index);
   5103 		/*.....................................................................
   5104 		If we've changed state, redraw everything; if we're starting the game,
   5105 		break out of the loop.  If we've just joined, send out a player query
   5106 		so I'll get added to the list instantly.
   5107 		.....................................................................*/
   5108 		if (event == EV_STATE_CHANGE) {
   5109 			display = REDRAW_ALL;
   5110 			if (joinstate==JOIN_GAME_START) {
   5111 CCDebugString ("C&C95 - Received 'GO' packet\n");
   5112 
   5113 				ready_to_go = true;
   5114 			} else {
   5115 
   5116 				/*..................................................................
   5117 				If we're newly-confirmed, immediately send out a player query
   5118 				..................................................................*/
   5119 				if (joinstate==JOIN_CONFIRMED) {
   5120 
   5121 					Clear_Player_List(&playerlist);
   5122 
   5123 					item = new char [MPLAYER_NAME_MAX + 4];
   5124 					if (MPlayerHouse==HOUSE_GOOD) {
   5125 						sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
   5126 					} else {
   5127 						sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
   5128 					}
   5129 					playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
   5130 
   5131 					who = new NodeNameType;
   5132 					strcpy(who->Name, MPlayerName);
   5133 					who->Address = IPXAddressClass();
   5134 					who->Player.House = MPlayerHouse;
   5135 					who->Player.Color = MPlayerColorIdx;
   5136 					Players.Add (who);
   5137 
   5138 					Send_Join_Queries (game_index, 0, 1);
   5139 				} else {
   5140 
   5141 					/*..................................................................
   5142 					If we've been rejected, clear any messages we may have been typing.
   5143 					..................................................................*/
   5144 					if (joinstate==JOIN_REJECTED) {
   5145 
   5146 						//
   5147 						// Remove myself from the player list box
   5148 						//
   5149 						item = (char *)(playerlist.Get_Item(0));
   5150 						if (item){
   5151 							playerlist.Remove_Item(item);
   5152 							delete [] item;
   5153 							playerlist.Flag_To_Redraw();
   5154 						}
   5155 
   5156 						//
   5157 						// Remove myself from the Players list
   5158 						//
   5159 						if (Players.Count()){
   5160 							who = Players[0];
   5161 							Players.Delete(0);
   5162 							delete who;
   5163 						}
   5164 					}
   5165 				}
   5166 			}
   5167 		} else
   5168 
   5169 		/*.....................................................................
   5170 		If a new game is detected, and it's the first game on our list,
   5171 		automatically send out a player query for that game.
   5172 		.....................................................................*/
   5173 		if (event == EV_NEW_GAME && gamelist.Count()==1) {
   5174 			gamelist.Set_Selected_Index(0);
   5175 			game_index = gamelist.Current_Index();
   5176 			Send_Join_Queries (game_index, 0, 1);
   5177 		} else
   5178 
   5179 		/*.....................................................................
   5180 		If the game options have changed, print them.
   5181 		.....................................................................*/
   5182 		if (event == EV_GAME_OPTIONS) {
   5183 			parms_received = 1;
   5184 			display = REDRAW_MESSAGE;
   5185 		} else
   5186 
   5187 		/*.....................................................................
   5188 		Draw an incoming message
   5189 		.....................................................................*/
   5190 		if (event == EV_MESSAGE) {
   5191 			display = REDRAW_MESSAGE;
   5192 		} else
   5193 
   5194 		/*.....................................................................
   5195 		A game before the one I've selected is gone, so we have a new index now.
   5196 		'game_index' must be kept set to the currently-selected list item, so
   5197 		we send out queries for the currently-selected game.  It's therefore
   5198 		imperative that we detect any changes to the game list.
   5199 		If we're joined in a game, we must decrement our game_index to keep
   5200 		it aligned with the game we're joined to.
   5201 		.....................................................................*/
   5202 		if (event == EV_GAME_SIGNOFF) {
   5203 			if (joinstate==JOIN_CONFIRMED) {
   5204 				game_index--;
   5205 				join_index--;
   5206 				gamelist.Set_Selected_Index(join_index);
   5207 			} else {
   5208 				gamelist.Flag_To_Redraw();
   5209 				Clear_Player_List(&playerlist);
   5210 				game_index = gamelist.Current_Index();
   5211 				Send_Join_Queries (game_index, 0, 1);
   5212 			}
   5213 		}
   5214 
   5215 		/*---------------------------------------------------------------------
   5216 		Service the Ipx connections
   5217 		---------------------------------------------------------------------*/
   5218 		Ipx.Service();
   5219 
   5220 		/*---------------------------------------------------------------------
   5221 		Clean out the Game List; if an old entry is found:
   5222 		- Remove it
   5223 		- Clear the player list
   5224 		- Send queries for the new selected game, if there is one
   5225 		---------------------------------------------------------------------*/
   5226 		for (i = 0; i < Games.Count(); i++) {
   5227 			if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
   5228 				Games.Delete(Games[i]);
   5229 				item = (char *)(gamelist.Get_Item (i));
   5230 				gamelist.Remove_Item (item);
   5231 				delete [] item;
   5232 				if (i <= game_index) {
   5233 					gamelist.Flag_To_Redraw();
   5234 					Clear_Player_List(&playerlist);
   5235 					game_index = gamelist.Current_Index();
   5236 					Send_Join_Queries (game_index, 0, 1);
   5237 				}
   5238 			}
   5239 		}
   5240 
   5241 		/*
   5242 		** If we were flagged to start the game and we recognise both players then quit the loop
   5243 		*/
   5244 
   5245 //char ddkks[128];
   5246 //sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
   5247 //CCDebugString (ddkks);
   5248 		if (ready_to_go){	// && Players.Count() == InternetMaxPlayers){
   5249 			rc = 0;
   5250 			process = false;
   5251 		}
   5252 
   5253 		/*---------------------------------------------------------------------
   5254 		Service the sounds & score; GameActive must be false at this point,
   5255 		so Call_Back() doesn't intercept global messages from me!
   5256 		---------------------------------------------------------------------*/
   5257 		Call_Back();
   5258 	}
   5259 
   5260 	/*------------------------------------------------------------------------
   5261 	Establish connections with all other players.
   5262 	------------------------------------------------------------------------*/
   5263 	if (rc == 0) {
   5264 		/*.....................................................................
   5265 		If the other guys are playing a scenario I don't have (sniff), I can't
   5266 		play.  Try to bail gracefully.
   5267 		.....................................................................*/
   5268 		if (ScenarioIdx==-1) {
   5269 			CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
   5270 
   5271 			//
   5272 			// Remove myself from the player list box
   5273 			//
   5274 			item = (char *)(playerlist.Get_Item(0));
   5275 			playerlist.Remove_Item(item);
   5276 			delete [] item;
   5277 			playerlist.Flag_To_Redraw();
   5278 
   5279 			//
   5280 			// Remove myself from the Players list
   5281 			//
   5282 			who = Players[0];
   5283 			Players.Delete(0);
   5284 			delete who;
   5285 
   5286 			memset (&GPacket, 0, sizeof(GlobalPacketType));
   5287 
   5288 			GPacket.Command = NET_SIGN_OFF;
   5289 			strcpy (GPacket.Name, MPlayerName);
   5290 
   5291 			for (i = 0; i < Players.Count(); i++) {
   5292 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
   5293 					&(Players[i]->Address));
   5294 				Ipx.Service();
   5295 			}
   5296 
   5297 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   5298 				0, NULL);
   5299 			Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
   5300 				0, NULL);
   5301 
   5302 			if (IsBridge) {
   5303 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   5304 					&BridgeNet);
   5305 				Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
   5306 					&BridgeNet);
   5307 			}
   5308 
   5309 			while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
   5310 
   5311 			rc = -1;
   5312 
   5313 		} else {
   5314 
   5315 			/*..................................................................
   5316 			Set the number of players in this game, and my ID
   5317 			..................................................................*/
   5318 			MPlayerCount = Players.Count();
   5319 			MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
   5320 
   5321 			/*..................................................................
   5322 			Get the scenario number
   5323 			..................................................................*/
   5324 			Scenario = ScenarioIdx;	//PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
   5325 
   5326 			/*..................................................................
   5327 			Form connections with all other players.  Form the IPX Connection ID
   5328 			from the player's Color and House.  This will let us extract any
   5329 			player's color & house at any time.  Fill in 'tmp_id' while we're
   5330 			doing this.
   5331 			..................................................................*/
   5332 			for (i = 0; i < Players.Count(); i++) {
   5333 
   5334 				/*...............................................................
   5335 				Only create the connection if it's not myself!
   5336 				...............................................................*/
   5337 				if (strcmp (MPlayerName, Players[i]->Name)) {
   5338 					id = Build_MPlayerID(Players[i]->Player.Color,
   5339 						Players[i]->Player.House);
   5340 
   5341 					tmp_id[i] = id;
   5342 
   5343 					Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
   5344 				} else {
   5345 					tmp_id[i] = MPlayerLocalID;
   5346 				}
   5347 			}
   5348 
   5349 #ifdef VIRTUAL_SUBNET_SERVER
   5350 			/*
   5351 			** Create an additional connection to the VSS
   5352 			*/
   5353 			if (UseVirtualSubnetServer){
   5354 				IPXAddressClass vss_global_address;
   5355 				NetNodeType vss_node;
   5356 				NetNumType	vss_net;
   5357 				memset (vss_net, 1, sizeof (vss_net));
   5358 				memset (vss_node, 0, sizeof (vss_node));
   5359 				vss_global_address.Set_Address(vss_net, vss_node);
   5360 				Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
   5361 			}
   5362 #endif	//VIRTUAL_SUBNET_SERVER
   5363 
   5364 			/*..................................................................
   5365 			Store every player's ID in the MPlayerID[] array.  This array will
   5366 			determine the order of event execution, so the ID's must be stored
   5367 			in the same order on all systems.
   5368 			..................................................................*/
   5369 			for (i = 0; i < MPlayerCount; i++) {
   5370 				min_index = 0;
   5371 				min_id = 0xff;
   5372 				for (j = 0; j < MPlayerCount; j++) {
   5373 					if (tmp_id[j] < min_id) {
   5374 						min_id = tmp_id[j];
   5375 						min_index = j;
   5376 					}
   5377 				}
   5378 				MPlayerID[i] = tmp_id[min_index];
   5379 				tmp_id[min_index] = 0xff;
   5380 			}
   5381 			/*..................................................................
   5382 			Fill in the array of player names, including my own.
   5383 			..................................................................*/
   5384 			for (i = 0; i < MPlayerCount; i++) {
   5385 				if (MPlayerID[i] == MPlayerLocalID) {
   5386 					strcpy (MPlayerNames[i], MPlayerName);
   5387 				} else {
   5388 					strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
   5389 				}
   5390 			}
   5391 		}
   5392 		/*---------------------------------------------------------------------
   5393 		Wait a while, polling the IPX service routines, to give our ACK
   5394 		a chance to get to the other system.  If he doesn't get our ACK, he'll
   5395 		be waiting the whole time we load MIX files.
   5396 		---------------------------------------------------------------------*/
   5397 		i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)120);
   5398 		starttime = TickCount.Time();
   5399 		while (TickCount.Time() - starttime < (unsigned)i) {
   5400 			Ipx.Service();
   5401 		}
   5402 	}
   5403 
   5404 	/*------------------------------------------------------------------------
   5405 	Init network timing values, using previous response times as a measure
   5406 	of what our retry delta & timeout should be.
   5407 	------------------------------------------------------------------------*/
   5408 	Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
   5409 		Ipx.Global_Response_Time() * 4);
   5410 
   5411 	/*------------------------------------------------------------------------
   5412 	Clear all lists
   5413 	------------------------------------------------------------------------*/
   5414 	Clear_Game_List(&gamelist);
   5415 	Clear_Player_List(&playerlist);
   5416 
   5417 	/*------------------------------------------------------------------------
   5418 	Restore screen
   5419 	------------------------------------------------------------------------*/
   5420 	Hide_Mouse();
   5421 	Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
   5422 	Blit_Hid_Page_To_Seen_Buff();
   5423 	Show_Mouse();
   5424 
   5425 	if (rc != -1){
   5426 		Wait_For_Focus();
   5427 	}
   5428 
   5429 	return(rc);
   5430 }
   5431 
   5432 
   5433 
   5434 #endif