Files
CnC_Tiberian_Dawn/NULLDLG.CPP.BAK
2025-02-27 14:50:48 +00:00

7581 lines
236 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
** Command & Conquer(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header: F:\projects\c&c\vcs\code\nulldlg.cpv 1.9 16 Oct 1995 16:52:12 JOE_BOSTIC $ */
/***************************************************************************
** 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 **
***************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : NULLDLG.CPP *
* *
* Programmer : Bill R. Randolph *
* *
* Start Date : 04/29/95 *
* *
* Last Update : April 29, 1995 [BRR] *
* *
*-------------------------------------------------------------------------*
* Functions: *
* Init_Null_Modem -- Initializes Null Modem communications *
* Shutdown_Modem -- Shuts down modem/null-modem communications *
* Test_Null_Modem -- Null-Modem test routine *
* Reconnect_Null_Modem -- allows user to reconnect *
* Destroy_Null_Connection -- destroys the given connection *
* Select_Serial_Dialog -- Serial Communications menu dialog *
* Com_Settings_Dialog -- Lets user select serial port settings *
* Com_Scenario_Dialog -- Serial game scenario selection dialog *
* Phone_Dialog -- Lets user edit phone directory & dial *
* Build_InitString_Listbox -- [re]builds the initstring entry listbox *
* Init_String_Compare -- for qsort *
* Build_Phone_Listbox -- [re]builds the phone entry listbox *
* Phone_Compare -- for qsort *
* Edit_Phone_Dialog -- lets user edit a phone book entry *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
#include "wincomm.h"
#include "tcpip.h"
//
// how much time (ticks) to go by before thinking other system
// is not responding.
//
#define PACKET_SENDING_TIMEOUT 1800
#define PACKET_CANCEL_TIMEOUT 900
//
// how much time (ticks) to go by before sending another packet
// of game options or serial connect.
//
#define PACKET_RETRANS_TIME 30
#define PACKET_REDRAW_TIME 60
static int Reconnect_Null_Modem( void );
static int Com_Settings_Dialog( SerialSettingsType *settings );
static int Phone_Dialog (void);
static void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index);
static int Init_String_Compare (const void *p1, const void *p2);
static void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf);
static int Phone_Compare (const void *p1, const void *p2);
static int Edit_Phone_Dialog (PhoneEntryClass *phone);
static bool Dial_Modem( SerialSettingsType *settings, bool reconnect );
static bool Answer_Modem( SerialSettingsType *settings, bool reconnect );
static void Modem_Echo( char c );
void Smart_Printf( char *format, ... );
void Hex_Dump_Data( char *buffer, int length );
void itoh( int i, char *s);
static SerialPacketType SendPacket;
static SerialPacketType ReceivePacket;
char TheirName[MPLAYER_NAME_MAX];
unsigned char TheirColor;
HousesType TheirHouse;
unsigned char TheirID;
static char DialString[ CWAITSTRBUF_MAX + PhoneEntryClass::PHONE_MAX_NUM - 1 ];
static SerialSettingsType *DialSettings;
#define SHOW_MONO 0
/***************************************************************************
* Init_Null_Modem -- Initializes Null Modem communications *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* true = OK, false = error *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
int Init_Null_Modem( SerialSettingsType *settings )
{
if ( NullModem.Init( settings->Port, settings->IRQ,
settings->Baud, 0, 8, 1 ) ) {
// settings->Baud, 'N', 8, 1 ) ) {
// NullModem.Change_IRQ_Priority( settings->IRQ );
return(true);
} else {
return(false);
}
}
/***************************************************************************
* Shutdown_Modem -- Shuts down modem/null-modem communications *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
void Shutdown_Modem( void )
{
if (!PlaybackGame) {
if (GameToPlay == GAME_MODEM) {
NullModem.Hangup_Modem();
}
}
//NullModem.Change_IRQ_Priority( 0 ); // reset priority of interrupts
//
// close port
//
NullModem.Shutdown();
}
/***************************************************************************
* Modem_Signoff -- sends EXIT event *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 08/03/1995 DRD : Created. *
*=========================================================================*/
void Modem_Signoff( void )
{
unsigned long starttime;
EventClass event;
if (!PlaybackGame) {
/*------------------------------------------------------------------------
Send a sign-off packet
------------------------------------------------------------------------*/
event.Type = EventClass::EXIT;
NullModem.Send_Message (&event,sizeof(EventClass),0);
NullModem.Send_Message (&event,sizeof(EventClass),0);
starttime = TickCount.Time();
while( (TickCount.Time() - starttime) > 30) {
NullModem.Service();
}
}
}
/***************************************************************************
* Test_Null_Modem -- Null-Modem test routine *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 0 = failure to connect; 1 = I'm the game owner, 2 = I'm not *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
int Test_Null_Modem( void )
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_CANCEL = 100,
};
/*........................................................................
Dialog variables
........................................................................*/
bool process = true; // process while true
KeyNumType input;
int retval;
unsigned long starttime;
int packetlen;
int x,y,width,height; // dialog dimensions
char buffer[80*3];
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
/*
** Determine the dimensions of the text to be used for the dialog box.
** These dimensions will control how the dialog box looks.
*/
strcpy( buffer, Text_String( TXT_WAITING_CONNECT ) );
Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
Format_Window_String(buffer, 200*factor, width, height);
width = MAX(width, 50*factor);
width += 40*factor;
height += 60*factor;
x = (320*factor - width) / 2;
y = (200*factor - height) / 2;
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 *factor)) >> 1),
y + height - (FontHeight + FontYSpacing + 2*factor) - 5*factor);
/*
------------------------------- Initialize -------------------------------
*/
Set_Logic_Page(SeenBuff);
process = true;
/*
............................ Create the list .............................
*/
commands = &cancelbtn;
commands->Flag_List_To_Redraw();
/*
............................ Draw the dialog .............................
*/
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Dialog_Box(x, y, width, height);
Draw_Caption(TXT_NONE, x, y, width);
Fancy_Text_Print(buffer, x + 20*factor, y + 25*factor, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
commands->Draw_All();
while (Get_Mouse_State() > 0) Show_Mouse();
/*
** This is supposed to be a direct connection so hang up any modem on this port
** just to annoy British Telecom
*/
/*
** Go into break mode
*/
SetCommBreak(SerialPort->Get_Port_Handle());
/*
** Send hangup command
*/
SerialPort->Write_To_Serial_Port ((unsigned char*)"ATH\r", strlen("ATH\r"));
CountDownTimerClass time;
time.Set(2*60);
while (time.Time()){}
/*
** Back out of break mode
*/
ClearCommBreak(SerialPort->Get_Port_Handle());
/*
** Drop DTR as well - just in case the modem still hasnt got the message
*/
EscapeCommFunction(SerialPort->Get_Port_Handle(), CLRDTR);
/*------------------------------------------------------------------------
Check for a packet. If we detect one, the other system has already been
started. Wait 1/2 sec for him to receive my ACK, then exit with success.
Note: The initial time must be a little longer than the resend delay.
Just in case we just missed the packet.
------------------------------------------------------------------------*/
starttime = TickCount.Time();
while ( TickCount.Time() - starttime < 80) {
NullModem.Service();
if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {
if (ReceivePacket.Command == SERIAL_CONNECT) {
//Smart_Printf( "Received SERIAL_CONNECT %d, ID %d \n", ReceivePacket.Seed, ReceivePacket.ID );
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 30)
NullModem.Service();
process = false;
retval = 2;
break;
}
}
}
/*------------------------------------------------------------------------
Send a packet across. As long as Num_Send() is non-zero, the other system
hasn't received it yet.
------------------------------------------------------------------------*/
if (process) {
memset (&SendPacket, 0, sizeof(SerialPacketType));
SendPacket.Command = SERIAL_CONNECT;
//
// put time from start of game for determining the host in case of tie.
//
SendPacket.Seed = TickCount.Time();
SendPacket.ID = (int) buffer; // address of buffer for more uniqueness.
//Smart_Printf( "Sending SERIAL_CONNECT %d, ID %d \n", SendPacket.Seed, SendPacket.ID );
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 80) {
NullModem.Service();
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
if (ReceivePacket.Command == SERIAL_CONNECT) {
//Smart_Printf( "Received2 SERIAL_CONNECT %d, ID %d \n", ReceivePacket.Seed, ReceivePacket.ID );
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 30)
NullModem.Service();
//
// whoever has the highest time is the host
//
if (ReceivePacket.Seed > SendPacket.Seed) {
process = false;
retval = 2;
} else {
if (ReceivePacket.Seed == SendPacket.Seed) {
if (ReceivePacket.ID > SendPacket.ID) {
process = false;
retval = 2;
} else
//
// if they are equal then it's a loopback cable or a modem
//
if (ReceivePacket.ID == SendPacket.ID) {
process = false;
retval = 3;
}
}
}
break;
}
}
}
}
starttime = TickCount.Time();
/*
-------------------------- Main Processing Loop --------------------------
*/
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
commands->Draw_All();
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
............................ Process input ............................
*/
switch (input) {
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
//Smart_Printf( "Canceled waiting for SERIAL_CONNECT\n" );
retval = 0;
process = false;
break;
default:
break;
}
/*.....................................................................
Service the connection.
.....................................................................*/
NullModem.Service();
if (NullModem.Num_Send() == 0) {
//Smart_Printf( "No more messages to send.\n" );
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
if (ReceivePacket.Command == SERIAL_CONNECT) {
//Smart_Printf( "Received3 SERIAL_CONNECT %d, ID %d \n", ReceivePacket.Seed, ReceivePacket.ID );
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 30)
NullModem.Service();
//
// whoever has the highest time is the host
//
if (ReceivePacket.Seed > SendPacket.Seed) {
process = false;
retval = 2;
} else {
if (ReceivePacket.Seed == SendPacket.Seed) {
if (ReceivePacket.ID > SendPacket.ID) {
process = false;
retval = 2;
} else {
//
// if they are equal then it's a loopback cable or a modem
//
if (ReceivePacket.ID == SendPacket.ID) {
process = false;
retval = 3;
}
}
}
}
} else {
retval = 0;
process = false;
}
} else {
retval = 1;
process = false;
}
}
if (TickCount.Time() - starttime > 3600) { // only wait 1 minute
retval = 0;
process = false;
}
} /* end of while */
return( retval );
}
/***************************************************************************
* Reconnect_Modem -- allows user to reconnect *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 0 = failure to connect; 1 = connect OK *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
int Reconnect_Modem( void )
{
int status;
int modemstatus;
switch (ModemGameToPlay) {
case (MODEM_NULL_HOST):
case (MODEM_NULL_JOIN):
status = Reconnect_Null_Modem();
break;
case (MODEM_DIALER):
modemstatus = NullModem.Get_Modem_Status();
if ( (modemstatus & CD_SET) ) {
//Smart_Printf( "Dial Modem connection error! Attempting reconnect....\n" );
status = Reconnect_Null_Modem();
} else {
status = Dial_Modem( DialSettings, true );
}
break;
case (MODEM_ANSWERER):
modemstatus = NullModem.Get_Modem_Status();
if ( (modemstatus & CD_SET) ) {
//Smart_Printf( "Answer Modem connection error! Attempting reconnect....\n" );
status = Reconnect_Null_Modem();
} else {
status = Answer_Modem( DialSettings, true );
}
break;
}
return( status );
}
/***************************************************************************
* Reconnect_Null_Modem -- allows user to reconnect *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 0 = failure to connect; 1 = connect OK *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
static int Reconnect_Null_Modem( void )
{
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_CANCEL = 100,
};
/*........................................................................
Dialog variables
........................................................................*/
bool process = true; // process while true
KeyNumType input;
int retval;
unsigned long starttime;
unsigned long lastmsgtime;
int packetlen;
int x,y,width,height; // dialog dimensions
char buffer[80*3];
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
/*
** Determine the dimensions of the text to be used for the dialog box.
** These dimensions will control how the dialog box looks.
*/
strcpy( buffer, Text_String( TXT_NULL_CONNERR_CHECK_CABLES ) );
Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
Format_Window_String(buffer, 200, width, height);
width = MAX(width, 50);
width += 40;
height += 60;
x = (320 - width) / 2;
y = (200 - height) / 2;
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8)) >> 1),
y + height - (FontHeight + FontYSpacing + 2) - 5);
/*
------------------------------- Initialize -------------------------------
*/
Set_Logic_Page(SeenBuff);
process = true;
/*
............................ Create the list .............................
*/
commands = &cancelbtn;
commands->Flag_List_To_Redraw();
/*
............................ Draw the dialog .............................
*/
Hide_Mouse();
Dialog_Box(x, y, width, height);
Draw_Caption(TXT_NONE, x, y, width);
Fancy_Text_Print(buffer, x + 20, y + 25, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
commands->Draw_All();
Show_Mouse();
/*
-------------------------- Main Processing Loop --------------------------
*/
starttime = lastmsgtime = TickCount.Time();
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
commands->Draw_All();
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
............................ Process input ............................
*/
switch (input) {
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
retval = false;
process = false;
break;
default:
break;
}
/*.....................................................................
Service the connection.
.....................................................................*/
NullModem.Service();
/*.....................................................................
Resend our message if it's time
.....................................................................*/
if (TickCount.Time() - starttime > PACKET_RETRANS_TIME) {
starttime = TickCount.Time();
SendPacket.Command = SERIAL_CONNECT;
SendPacket.ID = MPlayerLocalID;
//Smart_Printf( "Sending a SERIAL_CONNECT packet !!!!!!!!\n" );
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);
}
/*.....................................................................
Check for an incoming message
.....................................................................*/
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
lastmsgtime = TickCount.Time();
if (ReceivePacket.Command == SERIAL_CONNECT) {
//Smart_Printf( "Received a SERIAL_CONNECT packet !!!!!!!!\n" );
// are we getting our own packets back??
if (ReceivePacket.ID == MPlayerLocalID) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
retval = false;
process = false;
break;
}
/*...............................................................
OK, we got our message; now we have to make certain the other
guy gets his, so send him one with an ACK required.
...............................................................*/
SendPacket.Command = SERIAL_CONNECT;
SendPacket.ID = MPlayerLocalID;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 60)
NullModem.Service();
retval = true;
process = false;
}
}
//
// timeout if we do not get any packets
//
if (TickCount.Time() - lastmsgtime > PACKET_CANCEL_TIMEOUT) {
retval = false;
process = false;
}
} /* end of while */
return( retval );
}
/***********************************************************************************************
* Destroy_Null_Connection -- destroys the given connection *
* *
* Call this routine when a connection goes bad, or another player signs off. *
* *
* INPUT: *
* id connection ID to destroy *
* error 0 = user signed off; 1 = connection error *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 07/31/1995 DRD : Created. *
*=============================================================================================*/
void Destroy_Null_Connection(int id, int error)
{
int i,j,idx;
HousesType house;
HouseClass *housep;
char txt[80];
if ( MPlayerCount == 1 ) {
return;
}
// find index for id
idx = -1;
for (i = 0; i < MPlayerCount; i++) {
if (MPlayerID[i] == (unsigned char)id) {
idx = i;
break;
}
}
if (idx == -1) {
return;
}
/*------------------------------------------------------------------------
Create a message to display to the user
------------------------------------------------------------------------*/
txt[0] = '\0';
if (error == 1) {
sprintf(txt,Text_String(TXT_CONNECTION_LOST), MPlayerNames[idx] );
}
else if (error == 0) {
sprintf(txt,Text_String(TXT_LEFT_GAME), MPlayerNames[idx] );
}
else if (error == -1) {
NullModem.Delete_Connection();
}
if (strlen(txt)) {
Messages.Add_Message (txt,
MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
Map.Flag_To_Redraw(false);
}
for (i = 0; i < MPlayerCount; i++) {
if (MPlayerID[i] == (unsigned char)id) {
/*..................................................................
Turn the player's house over to the computer's AI
..................................................................*/
house = MPlayerHouses[i];
housep = HouseClass::As_Pointer (house);
housep->IsHuman = false;
/*..................................................................
Move arrays back by one
..................................................................*/
for (j = i; j < MPlayerCount - 1; j++) {
MPlayerID[j] = MPlayerID[j + 1];
MPlayerHouses[j] = MPlayerHouses[j + 1];
strcpy (MPlayerNames[j], MPlayerNames[j+1]);
TheirProcessTime[j] = TheirProcessTime[j+1];
}
}
}
MPlayerCount--;
/*------------------------------------------------------------------------
If we're the last player left, tell the user.
------------------------------------------------------------------------*/
if (MPlayerCount == 1) {
sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
Messages.Add_Message (txt,
MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
Map.Flag_To_Redraw(false);
}
} /* end of Destroy_Null_Connection */
/***************************************************************************
* Select_Serial_Dialog -- Serial Communications menu dialog *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* GAME_MODEM user wants to play a modem game *
* GAME_NULL_MODEM user wants to play a null-modem game *
* GAME_NORMAL user hit Cancel *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
GameType Select_Serial_Dialog( void )
{
int rc;
// int value, i;
int com = -1, baud = -1;
int error = 0;
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 160 *factor; // dialog width
int d_dialog_h = 94 *factor; // dialog height
int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
// D_DIALOG_Y = ((200 - D_DIALOG_H) / 2), // dialog y-coord
int d_dialog_y = ((136*factor - d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 11*factor; // ht of 6-pt text
int d_margin = 7; // margin width/height
int d_dial_w = 90 *factor;
int d_dial_h = 9 *factor;
int d_dial_x = d_dialog_cx - d_dial_w / 2;
int d_dial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;
int d_answer_w = 90 *factor;
int d_answer_h = 9 *factor;
int d_answer_x = d_dialog_cx - d_answer_w / 2;
int d_answer_y = d_dial_y + d_dial_h + 2;
int d_nullmodem_w = 90 *factor;
int d_nullmodem_h = 9 *factor;
int d_nullmodem_x = d_dialog_cx - d_nullmodem_w / 2;
int d_nullmodem_y = d_answer_y + d_answer_h + 2;
int d_settings_w = 90 *factor;
int d_settings_h = 9 *factor;
int d_settings_x = d_dialog_cx - d_settings_w / 2;
int d_settings_y = d_nullmodem_y + d_nullmodem_h + 2;
#if (GERMAN | FRENCH)
int d_cancel_w = 50 *factor;
#else
int d_cancel_w = 40 *factor;
#endif
int d_cancel_h = 9 *factor;
int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
int d_cancel_y = d_settings_y + d_settings_h + d_margin;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_DIAL = 100,
BUTTON_ANSWER,
BUTTON_NULLMODEM,
BUTTON_SETTINGS,
BUTTON_CANCEL,
NUM_OF_BUTTONS = 5,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
bool process = true; // process while true
KeyNumType input;
char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
int tabs[] = {77}; // tabs for player list box
GameType retval; // return value
int selection;
bool pressed;
int curbutton;
TextButtonClass *buttons[NUM_OF_BUTTONS];
SerialSettingsType *settings;
bool selectsettings = false;
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
TextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL_MODEM,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_dial_x, d_dial_y, d_dial_w, d_dial_h);
TextButtonClass answerbtn(BUTTON_ANSWER, TXT_ANSWER_MODEM,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_answer_x, d_answer_y, d_answer_w, d_answer_h);
TextButtonClass nullmodembtn(BUTTON_NULLMODEM, TXT_NULL_MODEM,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_nullmodem_x, d_nullmodem_y, d_nullmodem_w, d_nullmodem_h);
TextButtonClass settingsbtn(BUTTON_SETTINGS, TXT_SETTINGS,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_settings_x, d_settings_y, d_settings_w, d_settings_h);
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_cancel_x, d_cancel_y);
#else
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
#endif
/*
------------------------------- Initialize -------------------------------
*/
Set_Logic_Page(SeenBuff);
/*........................................................................
Read the CC.INI file to extract default serial settings, scenario numbers
& descriptions, and the phone list.
........................................................................*/
Read_MultiPlayer_Settings ();
if (SerialDefaults.Port == 0 ||
SerialDefaults.IRQ == -1 ||
SerialDefaults.Baud == -1) {
selectsettings = true;
} else {
if ( NullModem.Detect_Port( &SerialDefaults ) != PORT_VALID ) {
selectsettings = true;
}
}
/*
............................ Create the list .............................
*/
commands = &dialbtn;
answerbtn.Add_Tail(*commands);
nullmodembtn.Add_Tail(*commands);
settingsbtn.Add_Tail(*commands);
cancelbtn.Add_Tail(*commands);
/*
......................... Fill array of button ptrs ......................
*/
curbutton = 0;
buttons[0] = &dialbtn;
buttons[1] = &answerbtn;
buttons[2] = &nullmodembtn;
buttons[3] = &settingsbtn;
buttons[4] = &cancelbtn;
buttons[curbutton]->Turn_On();
Keyboard::Clear();
Fancy_Text_Print(TXT_NONE, 0, 0, CC_GREEN, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Debug_Smart_Print = true;
MPlayerLocalID = 0xff; // set to invalid value
/*
-------------------------- Main Processing Loop --------------------------
*/
display = REDRAW_ALL;
process = true;
pressed = false;
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
if (display >= REDRAW_BACKGROUND) {
/*
..................... Refresh the backdrop ......................
*/
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
/*
..................... Draw the background .......................
*/
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
/*
..................... Redraw the buttons .......................
*/
commands->Draw_All();
/*
....................... Draw the labels .........................
*/
Draw_Caption (TXT_SELECT_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
............................ Process input ............................
*/
switch (input) {
case (BUTTON_DIAL | KN_BUTTON):
selection = BUTTON_DIAL;
pressed = true;
break;
case (BUTTON_ANSWER | KN_BUTTON):
selection = BUTTON_ANSWER;
pressed = true;
break;
case (BUTTON_NULLMODEM | KN_BUTTON):
selection = BUTTON_NULLMODEM;
pressed = true;
break;
case (BUTTON_SETTINGS | KN_BUTTON):
selection = BUTTON_SETTINGS;
pressed = true;
break;
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
selection = BUTTON_CANCEL;
pressed = true;
break;
case (KN_UP):
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton--;
if (curbutton < 0)
curbutton = (NUM_OF_BUTTONS - 1);
buttons[curbutton]->Turn_On();
buttons[curbutton]->Flag_To_Redraw();
break;
case (KN_DOWN):
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton++;
if (curbutton > (NUM_OF_BUTTONS - 1) )
curbutton = 0;
buttons[curbutton]->Turn_On();
buttons[curbutton]->Flag_To_Redraw();
break;
case (KN_RETURN):
selection = curbutton + BUTTON_DIAL;
pressed = true;
break;
default:
break;
}
if (pressed) {
//
// to make sure the selection is correct in case they used the mouse
//
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton = selection - BUTTON_DIAL;
buttons[curbutton]->Turn_On();
buttons[curbutton]->IsPressed = true;
buttons[curbutton]->Draw_Me(true);
switch (selection) {
case (BUTTON_DIAL):
if (selectsettings) {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
}
/*
** Remote-connect
*/
else if ( Phone_Dialog() ) {
if (PhoneBook[CurPhoneIdx]->Settings.Port == 0) {
settings = &SerialDefaults;
} else {
settings = &(PhoneBook[CurPhoneIdx]->Settings);
}
if (SerialPort){
delete SerialPort;
}
SerialPort = new WinModemClass;
if ( Init_Null_Modem( settings ) ) {
if (settings->CallWaitStringIndex == CALL_WAIT_CUSTOM) {
strcpy( DialString, settings->CallWaitString );
} else {
strcpy( DialString,
CallWaitStrings[ settings->CallWaitStringIndex ] );
}
strcat( DialString, PhoneBook[ CurPhoneIdx ]->Number );
if ( Dial_Modem( settings, false ) ) {
ModemGameToPlay = MODEM_DIALER;
if ( Com_Scenario_Dialog() ) {
retval = GAME_MODEM;
process = false;
}
}
if (process) { // restore to default
NullModem.Change_IRQ_Priority( 0 );
}
} else {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
}
}
if (process) {
buttons[curbutton]->IsPressed = false;
buttons[curbutton]->Flag_To_Redraw();
}
display = REDRAW_ALL;
break;
case (BUTTON_ANSWER):
if (selectsettings) {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
} else {
/*
** Remote-connect
*/
settings = &SerialDefaults;
if (SerialPort){
delete SerialPort;
}
SerialPort = new WinModemClass;
if ( Init_Null_Modem( settings ) ) {
if ( Answer_Modem( settings, false ) ) {
ModemGameToPlay = MODEM_ANSWERER;
if ( Com_Show_Scenario_Dialog() ) {
retval = GAME_MODEM;
process = false;
}
}
if (process) { // restore to default
NullModem.Change_IRQ_Priority( 0 );
}
} else {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
}
}
if (process) {
buttons[curbutton]->IsPressed = false;
buttons[curbutton]->Flag_To_Redraw();
}
display = REDRAW_ALL;
break;
case (BUTTON_NULLMODEM):
if (selectsettings) {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
} else {
/*
** Otherwise, remote-connect; save values if we're recording
*/
if (SerialPort){
delete SerialPort;
}
SerialPort = new WinNullModemClass;
if ( Init_Null_Modem( &SerialDefaults ) ) {
rc = Test_Null_Modem();
switch (rc) {
case (1):
ModemGameToPlay = MODEM_NULL_HOST;
if ( Com_Scenario_Dialog() ) {
retval = GAME_NULL_MODEM;
process = false;
}
break;
case (2):
ModemGameToPlay = MODEM_NULL_JOIN;
if ( Com_Show_Scenario_Dialog() ) {
retval = GAME_NULL_MODEM;
process = false;
}
break;
case (3):
CCMessageBox().Process( TXT_MODEM_OR_LOOPBACK );
break;
}
if (process) { // restore to default
NullModem.Change_IRQ_Priority( 0 );
}
} else {
CCMessageBox().Process(TXT_SELECT_SETTINGS);
}
}
if (process) {
buttons[curbutton]->IsPressed = false;
buttons[curbutton]->Flag_To_Redraw();
}
display = REDRAW_ALL;
break;
case (BUTTON_SETTINGS):
if ( Com_Settings_Dialog( &SerialDefaults ) ) {
Write_MultiPlayer_Settings ();
selectsettings = true;
if (SerialDefaults.Port != 0 &&
SerialDefaults.IRQ != -1 &&
SerialDefaults.Baud != -1) {
if ( NullModem.Detect_Port( &SerialDefaults ) == PORT_VALID) {
selectsettings = false;
}
}
}
buttons[curbutton]->IsPressed = false;
buttons[curbutton]->Flag_To_Redraw();
display = REDRAW_ALL;
break;
case (BUTTON_CANCEL):
retval = GAME_NORMAL;
process = false;
break;
}
pressed = false;
}
} /* end of while */
#if 0
if (retval == GAME_NORMAL) {
Debug_Smart_Print = false;
}
#endif
Debug_Smart_Print = false;
return( retval );
}
/***************************************************************************
* Com_Settings_Dialog -- Lets user select serial port settings *
* *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ *
* <20> Settings <20> *
* <20> <20> *
* <20> Port:____ IRQ:__ Baud:______ <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> *
* <20> <20> <20> <20> <20> <20> <20> <20> *
* <20> <20> <20> <20> <20> <20> <20> <20> *
* <20> <20> <20> <20> <20> <20> <20> <20> *
* <20> <20> <20> <20> <20> <20> <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> <20> *
* <20> Initialization: [Add] [Delete] <20> *
* <20> _____________________________ <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> *
* <20> <20> <20> <20> *
* <20> <20> <20> <20> *
* <20> <20> <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> <20> *
* <20> Call Waiting: <20> *
* <20> _______________ <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ [Tone Dialing] <20> *
* <20> <20> <20> <20> *
* <20> <20> <20> [Pulse Dialing] <20> *
* <20> <20> <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> <20> *
* <20> [OK] [Cancel] <20> *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *
* *
* INPUT: *
* settings ptr to SerialSettingsType structure *
* *
* OUTPUT: *
* true = OK, false = Cancel *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
static int Com_Settings_Dialog( SerialSettingsType *settings )
{
/* ###Change collision detected! C:\PROJECTS\CODE\NULLDLG.CPP... */
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 301 *factor; // dialog width
int d_dialog_h = 200 *factor; // dialog height
int d_dialog_x = ((320 *factor - d_dialog_w) / 2); // dialog x-coord
int d_dialog_y = ((200 *factor - d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 6 *factor +1; // ht of 6-pt text
int d_margin = 5 *factor; // margin width/height
#ifdef EDIT_IRQ
int d_portlist_w = 80 *factor;
int d_portlist_h = 35 *factor;
int d_portlist_x = d_dialog_x + (d_dialog_w / 6) - (d_portlist_w / 2);
int d_portlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 *factor;
int d_port_w = ((PORTBUF_MAX - 1) * 6 *factor) + 4 *factor;
int d_port_h = 9 *factor;
int d_port_x = d_portlist_x + 31 *factor;
int d_port_y = d_portlist_y - d_margin - d_txt6_h;
int d_irqlist_w = 80 *factor;
int d_irqlist_h = 35 *factor;
int d_irqlist_x = d_dialog_x + (d_dialog_w / 2) - (d_irqlist_w / 2);
int d_irqlist_y = d_portlist_y;
int d_irq_w = ((IRQBUF_MAX - 1) * 6 *factor) + 3 *factor;
int d_irq_h = 9 *factor;
int d_irq_x = d_irqlist_x + 25 *factor;
int d_irq_y = d_irqlist_y - d_margin - d_txt6_h;
int d_baudlist_w = 80 *factor;
int d_baudlist_h = 35 *factor;
int d_baudlist_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_baudlist_w / 2);
int d_baudlist_y = d_portlist_y;
int d_baud_w = ((BAUDBUF_MAX - 1) * 6 *factor) + 3 *factor;
int d_baud_h = 9 *factor;
int d_baud_x = d_baudlist_x + 31 *factor;
int d_baud_y = d_baudlist_y - d_margin - d_txt6_h;
#endif //EDIT_IRQ
int d_initstrlist_w = ((INITSTRBUF_MAX - 1) * 6 *factor) + 8 + 3 *factor;
int d_initstrlist_h = 21 *factor;
int d_initstrlist_x = d_dialog_cx - (d_initstrlist_w / 2);
int d_initstrlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 *factor +
35*factor +
((d_margin + d_txt6_h) * 2) + d_margin + 4 *factor;
int d_initstr_w = ((INITSTRBUF_MAX - 1) * 6 *factor) + 3 *factor;
int d_initstr_h = 9 *factor;
int d_initstr_x = d_initstrlist_x;
int d_initstr_y = d_initstrlist_y - d_margin - d_txt6_h;
#ifndef EDIT_IRQ
int d_portlist_w = 80 *factor;
int d_portlist_h = 35 *factor;
int d_portlist_x = d_initstrlist_x;
int d_portlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 *factor;
int d_port_w = ((PORTBUF_MAX - 1) * 6 *factor) + 4 *factor;
int d_port_h = 9 *factor;
int d_port_x = d_portlist_x + 31 *factor;
int d_port_y = d_portlist_y - d_margin - d_txt6_h;
int d_baudlist_w = 80 *factor;
int d_baudlist_h = 35 *factor;
int d_baudlist_x = d_portlist_x + d_portlist_w + 20 * factor;
int d_baudlist_y = d_portlist_y;
int d_baud_w = ((BAUDBUF_MAX - 1) * 6 *factor) + 3 *factor;
int d_baud_h = 9 *factor;
int d_baud_x = d_baudlist_x + 31 *factor;
int d_baud_y = d_baudlist_y - d_margin - d_txt6_h;
int d_inittype_w = 30*factor;
int d_inittype_h = 9*factor;
int d_inittype_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_inittype_w / 2);
int d_inittype_y = d_baud_y + 20*factor;
#endif //EDIT_IRQ
int d_add_w = 45 *factor;
int d_add_h = 9 *factor;
#ifdef FRENCH
int d_add_x = (d_dialog_cx - (d_add_w / 2))+34*factor;
#else
int d_add_x = d_dialog_cx - (d_add_w / 2);
#endif
int d_add_y = d_initstr_y - d_add_h - 3*factor;
int d_delete_w = 45 *factor;
int d_delete_h = 9 *factor;
#ifdef FRENCH
int d_delete_x = 14*factor + d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2);
#else
int d_delete_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2);
#endif
int d_delete_y = d_initstr_y - d_add_h - 3 *factor;
int d_cwaitstrlist_w = (((CWAITSTRBUF_MAX - 1) + 9) * 6 *factor) + 3 *factor;
int d_cwaitstrlist_h = 27 *factor;
int d_cwaitstrlist_x = d_initstrlist_x;
int d_cwaitstrlist_y = d_initstrlist_y + d_initstrlist_h + ((d_margin + d_txt6_h) * 2) + 2 *factor;
int d_cwaitstr_w = ((CWAITSTRBUF_MAX - 1) * 6 *factor) + 3 *factor;
int d_cwaitstr_h = 9 *factor;
int d_cwaitstr_x = d_cwaitstrlist_x;
int d_cwaitstr_y = d_cwaitstrlist_y - d_margin - d_txt6_h;
int d_tone_w = 80 *factor;
int d_tone_h = 9 *factor;
int d_tone_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_tone_w / 2);
int d_tone_y = d_cwaitstrlist_y;
int d_pulse_w = 80 *factor;
int d_pulse_h = 9 *factor;
int d_pulse_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_pulse_w / 2);
int d_pulse_y = d_tone_y + d_tone_h + d_margin;
int d_save_w = 40 *factor;
int d_save_h = 9 *factor;
int d_save_x = d_dialog_x + (d_dialog_w / 3) - (d_save_w / 2);
int d_save_y = d_dialog_y + d_dialog_h - d_save_h - d_margin - 2 *factor;
#if (GERMAN | FRENCH)
int d_cancel_w = 50 *factor;
#else
int d_cancel_w = 40 *factor;
#endif
int d_cancel_h = 9 *factor;
int d_cancel_x = d_dialog_x + ((d_dialog_w * 2) / 3) - (d_cancel_w / 2);
int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin - 2 *factor;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_PORT = 100,
BUTTON_PORTLIST,
BUTTON_IRQ,
BUTTON_IRQLIST,
BUTTON_BAUD,
BUTTON_BAUDLIST,
BUTTON_INITSTR,
BUTTON_INITSTRLIST,
BUTTON_ADD,
BUTTON_DELETE,
BUTTON_CWAITSTR,
BUTTON_CWAITSTRLIST,
BUTTON_TONE,
BUTTON_PULSE,
BUTTON_SAVE,
BUTTON_INITTYPE,
BUTTON_CANCEL,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
static char *portname[5] = {
"COM1 - 3F8",
"COM2 - 2F8",
"COM3 - 3E8",
"COM4 - 2E8",
"CUSTOM - ????"
};
#ifdef EDIT_IRQ
static char *irqname[5] = {
"2 / 9",
"3 - [COM2 & 4]",
"4 - [COM1 & 3]",
"5",
"CUSTOM - ??"
};
static int _irqidx[4] = {
2,
1,
2,
1
};
#endif // EDIT_IRQ
static char *baudname[5] = {
"14400",
"19200",
"28800",
"38400",
"57600",
};
static char *init_types[2] = {
"Normal",
"Full",
};
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
BOOL process = true; // process while true
KeyNumType input;
char * item; // general-purpose string
char * temp; // general-purpose string
char portbuf[ PORTBUF_MAX ] = {0}; // buffer for port
#ifdef EDIT_IRQ
char irqbuf[ IRQBUF_MAX ] = {0}; // buffer for irq
#endif //EDIT_IRQ
char baudbuf[ BAUDBUF_MAX ] = {0}; // buffer for baud
char initstrbuf[ INITSTRBUF_MAX ] = {0}; // buffer for init string
char cwaitstrbuf[ CWAITSTRBUF_MAX ] = {0}; // buffer for call waiting string
int port_index = 1; // index of currently-selected port (default = com2)
#ifdef EDIT_IRQ
int irq_index = 1; // index of currently-selected irq (default = 3)
#endif //EDIT_IRQ
int baud_index = 1; // index of currently-selected baud (default = 19200)
int initstr_index = 0; // index of currently-selected modem init (default = "ATZ")
int cwaitstr_index = CALL_WAIT_CUSTOM; // index of currently-selected call waiting (default = "")
int rc = 0; // -1 = user cancelled, 1 = New
int i; // loop counter
int pos;
int len;
int firsttime = 1;
SerialSettingsType tempsettings;
DetectPortType dpstatus;
char init_text[32];
void const *up_button;
void const *down_button;
if (InMainLoop){
up_button = Hires_Retrieve("BTN-UP.SHP");
down_button = Hires_Retrieve("BTN-DN.SHP");
}else{
up_button = Hires_Retrieve("BTN-UP2.SHP");
down_button = Hires_Retrieve("BTN-DN2.SHP");
}
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
EditClass port_edt (BUTTON_PORT,
portbuf, PORTBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_port_x, d_port_y, d_port_w, d_port_h, EditClass::ALPHANUMERIC);
ListClass portlist(BUTTON_PORTLIST,
d_portlist_x, d_portlist_y, d_portlist_w, d_portlist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
#ifdef EDIT_IRQ
EditClass irq_edt (BUTTON_IRQ,
irqbuf, IRQBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_irq_x, d_irq_y, d_irq_w, d_irq_h, EditClass::NUMERIC);
ListClass irqlist(BUTTON_IRQLIST,
d_irqlist_x, d_irqlist_y, d_irqlist_w, d_irqlist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
#endif //EDIT_IRQ
EditClass baud_edt (BUTTON_BAUD,
baudbuf, BAUDBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_baud_x, d_baud_y, d_baud_w, d_baud_h, EditClass::NUMERIC);
ListClass baudlist(BUTTON_BAUDLIST,
d_baudlist_x, d_baudlist_y, d_baudlist_w, d_baudlist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
EditClass initstr_edt (BUTTON_INITSTR,
initstrbuf, INITSTRBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_initstr_x, d_initstr_y, d_initstr_w, d_initstr_h, EditClass::ALPHANUMERIC);
ListClass initstrlist(BUTTON_INITSTRLIST,
d_initstrlist_x, d_initstrlist_y, d_initstrlist_w, d_initstrlist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
TextButtonClass addbtn(BUTTON_ADD, TXT_ADD,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#ifdef FRENCH
d_add_x, d_add_y);
#else
d_add_x, d_add_y, d_add_w, d_add_h);
#endif
TextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#ifdef FRENCH
d_delete_x, d_delete_y);
#else
d_delete_x, d_delete_y, d_delete_w, d_delete_h);
#endif
EditClass cwaitstr_edt (BUTTON_CWAITSTR,
cwaitstrbuf, CWAITSTRBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_cwaitstr_x, d_cwaitstr_y, d_cwaitstr_w, d_cwaitstr_h, EditClass::ALPHANUMERIC);
ListClass cwaitstrlist(BUTTON_CWAITSTRLIST,
d_cwaitstrlist_x, d_cwaitstrlist_y, d_cwaitstrlist_w, d_cwaitstrlist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
TextButtonClass tonebtn(BUTTON_TONE, TXT_TONE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_tone_x, d_tone_y, d_tone_w, d_tone_h);
TextButtonClass pulsebtn(BUTTON_PULSE, TXT_PULSE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_pulse_x, d_pulse_y, d_pulse_w, d_pulse_h);
TextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_save_x, d_save_y);
#else
d_save_x, d_save_y, d_save_w, d_save_h);
#endif
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_cancel_x, d_cancel_y);
#else
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
#endif
#if (0)
TextButtonClass inittypebutton(BUTTON_INITTYPE, init_text,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_inittype_x, d_inittype_y, d_inittype_w, d_inittype_h);
#endif //(0)
/*
----------------------------- Various Inits ------------------------------
*/
memcpy( &tempsettings, settings, sizeof(SerialSettingsType) );
strcpy (init_text, init_types[tempsettings.Init]);
if (tempsettings.Port == 0) {
tempsettings.Port = 0x2f8;
}
if (tempsettings.IRQ == -1) {
tempsettings.IRQ = 3;
}
if (tempsettings.Baud == -1) {
tempsettings.Baud = 19200;
}
/*........................................................................
Set the current indices
........................................................................*/
switch ( tempsettings.Port ) {
case ( 0x3f8 ):
port_index = 0;
strcpy (portbuf, "COM1");
break;
case ( 0x2f8 ):
port_index = 1;
strcpy (portbuf, "COM2");
break;
case ( 0x3e8 ):
port_index = 2;
strcpy (portbuf, "COM3");
break;
case ( 0x2e8 ):
port_index = 3;
strcpy (portbuf, "COM4");
break;
default:
port_index = 4;
sprintf (portbuf, "%x", tempsettings.Port);
temp = strchr( portname[4], '-' );
if ( temp ) {
pos = (int)(temp - portname[4]) + 2;
len = strlen( portbuf );
strncpy( portname[4] + pos, portbuf, len );
*(portname[4] + pos + len) = 0;
}
break;
}
#ifdef EDIT_IRQ
switch ( tempsettings.IRQ ) {
case ( 2 ):
irq_index = 0;
strcpy (irqbuf, "2");
break;
case ( 3 ):
irq_index = 1;
strcpy (irqbuf, "3");
break;
case ( 4 ):
irq_index = 2;
strcpy (irqbuf, "4");
break;
case ( 5 ):
irq_index = 3;
strcpy (irqbuf, "5");
break;
default:
irq_index = 4;
sprintf (irqbuf, "%d", tempsettings.IRQ);
temp = strchr( irqname[4], '-' );
if ( temp ) {
pos = (int)(temp - irqname[4]) + 2;
len = strlen( irqbuf );
strncpy( irqname[4] + pos, irqbuf, len );
*(irqname[4] + pos + len) = 0;
}
break;
}
#endif //EDIT_IRQ
if (tempsettings.Baud == 14400) {
baud_index = 0;
} else {
if (tempsettings.Baud == 19200) {
baud_index = 1;
} else {
if (tempsettings.Baud == 28800) {
baud_index = 2;
} else {
if (tempsettings.Baud == 38400) {
baud_index = 3;
} else {
baud_index = 4;
}
}
}
}
sprintf (baudbuf, "%d", tempsettings.Baud);
/*........................................................................
Set up the port list box & edit box
........................................................................*/
for (i = 0; i < 5; i++) {
portlist.Add_Item( portname[ i ] );
}
portlist.Set_Selected_Index( port_index );
port_edt.Set_Text( portbuf, PORTBUF_MAX );
/*........................................................................
Set up the IRQ list box & edit box
........................................................................*/
#ifdef EDIT_IRQ
for (i = 0; i < 5; i++) {
irqlist.Add_Item( irqname[ i ] );
}
irqlist.Set_Selected_Index( irq_index );
irq_edt.Set_Text( irqbuf, IRQBUF_MAX );
#endif //EDIT_IRQ
/*........................................................................
Set up the baud rate list box & edit box
........................................................................*/
for (i = 0; i < 5; i++) {
baudlist.Add_Item( baudname[ i ] );
}
baudlist.Set_Selected_Index( baud_index );
baud_edt.Set_Text( baudbuf, BAUDBUF_MAX );
initstr_index = tempsettings.InitStringIndex;
Build_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf, &initstr_index);
/*........................................................................
Set up the cwait rate list box & edit box
........................................................................*/
cwaitstr_index = tempsettings.CallWaitStringIndex;
for (i = 0; i < CALL_WAIT_STRINGS_NUM; i++) {
if ( i == CALL_WAIT_CUSTOM ) {
item = CallWaitStrings[ i ];
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
len = strlen( tempsettings.CallWaitString );
strncpy( item + pos, tempsettings.CallWaitString, len );
*(item + pos + len) = 0;
if (i == cwaitstr_index) {
strncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );
}
}
} else {
if (i == cwaitstr_index) {
strncpy( cwaitstrbuf, CallWaitStrings[ i ], CWAITSTRBUF_MAX );
}
}
cwaitstrlist.Add_Item( CallWaitStrings[ i ] );
}
cwaitstrlist.Set_Selected_Index( cwaitstr_index );
cwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );
/*........................................................................
Build the button list
........................................................................*/
commands = &cancelbtn;
port_edt.Add_Tail(*commands);
portlist.Add_Tail(*commands);
#ifdef EDIT_IRQ
irq_edt.Add_Tail(*commands);
irqlist.Add_Tail(*commands);
#endif // EDIT_IRQ
baud_edt.Add_Tail(*commands);
baudlist.Add_Tail(*commands);
//inittypebutton.Add_Tail(*commands);
initstr_edt.Add_Tail(*commands);
initstrlist.Add_Tail(*commands);
addbtn.Add_Tail(*commands);
deletebtn.Add_Tail(*commands);
cwaitstr_edt.Add_Tail(*commands);
cwaitstrlist.Add_Tail(*commands);
tonebtn.Add_Tail(*commands);
pulsebtn.Add_Tail(*commands);
savebtn.Add_Tail(*commands);
if (tempsettings.DialMethod == DIAL_TOUCH_TONE) {
tonebtn.Turn_On();
} else {
pulsebtn.Turn_On();
}
/*
---------------------------- Processing loop -----------------------------
*/
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
if (display >= REDRAW_BACKGROUND) {
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
// init font variables
Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*...............................................................
Dialog & Field labels
...............................................................*/
Draw_Caption (TXT_SETTINGS, d_dialog_x, d_dialog_y, d_dialog_w);
Fancy_Text_Print( TXT_PORT_COLON,
d_port_x - 3, d_port_y + 1 *factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
#ifdef EDIT_IRQ
Fancy_Text_Print( TXT_IRQ_COLON,
d_irq_x - 3, d_irq_y + 1 *factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
#endif //EDIT_IRQ
Fancy_Text_Print( TXT_BAUD_COLON,
d_baud_x - 3, d_baud_y + 1 *factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print( TXT_INIT_STRING,
d_initstr_x, d_initstr_y - d_txt6_h - 3 *factor,
CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print( TXT_CWAIT_STRING,
d_cwaitstr_x, d_cwaitstr_y - d_txt6_h - 3 *factor,
CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
#if (0)
Fancy_Text_Print ( "Modem Init",
d_inittype_x, d_inittype_y - d_txt6_h - d_margin,
CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
#endif //(0)
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
cancelbtn.Flag_To_Redraw();
port_edt.Flag_To_Redraw();
portlist.Flag_To_Redraw();
#ifdef EDIT_IRQ
irq_edt.Flag_To_Redraw();
irqlist.Flag_To_Redraw();
#endif // EDIT_IRQ
baud_edt.Flag_To_Redraw();
baudlist.Flag_To_Redraw();
//inittypebutton.Flag_To_Redraw();
initstr_edt.Flag_To_Redraw();
initstrlist.Flag_To_Redraw();
addbtn.Flag_To_Redraw();
deletebtn.Flag_To_Redraw();
cwaitstr_edt.Flag_To_Redraw();
cwaitstrlist.Flag_To_Redraw();
tonebtn.Flag_To_Redraw();
pulsebtn.Flag_To_Redraw();
savebtn.Flag_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
if ( firsttime ) {
port_edt.Set_Focus();
port_edt.Flag_To_Redraw();
input = commands->Input();
firsttime = 0;
}
/*
---------------------------- Process input ----------------------------
*/
switch (input) {
#if (0)
case (BUTTON_INITTYPE | KN_BUTTON):
tempsettings.Init = !tempsettings.Init;
strcpy (init_text, init_types[tempsettings.Init]);
inittypebutton.Flag_To_Redraw();
break;
#endif //(0)
case (BUTTON_PORT | KN_BUTTON):
item = (char *)portlist.Current_Item();
if (port_index < 4) {
temp = strchr( item, ' ' );
if ( !temp ) {
strncpy( portbuf, item, PORTBUF_MAX );
} else {
pos = (int)(temp - item);
strncpy( portbuf, item, pos );
portbuf[pos] = 0;
}
port_edt.Set_Text( portbuf, PORTBUF_MAX );
port_edt.Flag_To_Redraw();
#ifdef EDIT_IRQ
irq_edt.Set_Focus();
irq_edt.Flag_To_Redraw();
#endif //EDIT_IRQ
} else {
strupr( portbuf );
if ( stricmp(portbuf, "3F8") == 0 ) {
port_index = 0;
portlist.Set_Selected_Index( port_index );
strcpy (portbuf, "COM1");
display = REDRAW_BUTTONS;
}
else if ( stricmp(portbuf, "2F8") == 0 ) {
port_index = 1;
portlist.Set_Selected_Index( port_index );
strcpy (portbuf, "COM2");
display = REDRAW_BUTTONS;
}
else if ( stricmp(portbuf, "3E8") == 0 ) {
port_index = 2;
portlist.Set_Selected_Index( port_index );
strcpy (portbuf, "COM3");
display = REDRAW_BUTTONS;
}
else if ( stricmp(portbuf, "2E8") == 0 ) {
port_index = 3;
portlist.Set_Selected_Index( port_index );
strcpy (portbuf, "COM4");
display = REDRAW_BUTTONS;
}
else if ( strncmp(portbuf, "COM", 3) == 0 ) {
display = REDRAW_BUTTONS;
switch ( (portbuf[3] - '0') ) {
case 1:
port_index = 0;
break;
case 2:
port_index = 1;
break;
case 3:
port_index = 2;
break;
case 4:
port_index = 3;
break;
default:
CCMessageBox().Process( TXT_INVALID_PORT_ADDRESS );
port_edt.Set_Focus();
display = REDRAW_ALL;
break;
}
portlist.Set_Selected_Index( port_index );
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
len = strlen( portbuf );
strncpy( item + pos, portbuf, len );
*(item + pos + len) = 0;
display = REDRAW_BUTTONS;
}
}
#ifdef EDIT_IRQ
if (display == REDRAW_BUTTONS) {
irq_edt.Set_Focus();
irq_edt.Flag_To_Redraw();
}
#endif //EDIT_IRQ
}
break;
case (BUTTON_PORTLIST | KN_BUTTON):
if (portlist.Current_Index() != port_index) {
port_index = portlist.Current_Index();
item = (char *)portlist.Current_Item();
if (port_index < 4) {
temp = strchr( item, ' ' );
if ( !temp ) {
strncpy( portbuf, item, PORTBUF_MAX );
} else {
pos = (int)(temp - item);
strncpy( portbuf, item, pos );
portbuf[pos] = 0;
}
port_edt.Clear_Focus();
// auto select the irq for port
#ifdef EDIT_IRQ
irq_index = _irqidx[ port_index ];
irqlist.Set_Selected_Index( irq_index );
item = (char *)irqlist.Current_Item();
temp = strchr( item, ' ' );
if ( !temp ) {
strncpy( irqbuf, item, 2 );
} else {
pos = (int)(temp - item);
strncpy( irqbuf, item, pos );
irqbuf[pos] = 0;
}
irq_edt.Clear_Focus();
#endif //EDIT_IRQ
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
if ( *(item + pos) == '?' ) {
portbuf[0] = 0;
} else {
strncpy( portbuf, item + pos, PORTBUF_MAX );
}
}
port_edt.Set_Focus();
}
port_edt.Set_Text( portbuf, PORTBUF_MAX );
display = REDRAW_BUTTONS;
} else {
if (port_index < 4) {
port_edt.Clear_Focus();
} else {
port_edt.Set_Focus();
}
display = REDRAW_BUTTONS;
}
break;
#ifdef EDIT_IRQ
case (BUTTON_IRQ | KN_BUTTON):
item = (char *)irqlist.Current_Item();
if (irq_index < 4) {
temp = strchr( item, ' ' );
if ( !temp ) {
strncpy( irqbuf, item, IRQBUF_MAX );
} else {
pos = (int)(temp - item);
strncpy( irqbuf, item, pos );
irqbuf[pos] = 0;
}
irq_edt.Set_Text( irqbuf, IRQBUF_MAX );
irq_edt.Flag_To_Redraw();
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
len = strlen( irqbuf );
strncpy( item + pos, irqbuf, len );
*(item + pos + len) = 0;
display = REDRAW_BUTTONS;
}
}
baud_edt.Set_Focus();
baud_edt.Flag_To_Redraw();
break;
case (BUTTON_IRQLIST | KN_BUTTON):
if (irqlist.Current_Index() != irq_index) {
irq_index = irqlist.Current_Index();
item = (char *)irqlist.Current_Item();
if (irq_index < 4) {
temp = strchr( item, ' ' );
if ( !temp ) {
strncpy( irqbuf, item, IRQBUF_MAX );
} else {
pos = (int)(temp - item);
strncpy( irqbuf, item, pos );
irqbuf[pos] = 0;
}
irq_edt.Clear_Focus();
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
if ( *(item + pos) == '?' ) {
irqbuf[0] = 0;
} else {
strncpy( irqbuf, item + pos, IRQBUF_MAX );
}
}
irq_edt.Set_Focus();
}
irq_edt.Set_Text( irqbuf, IRQBUF_MAX );
} else {
if (irq_index < 4) {
irq_edt.Clear_Focus();
} else {
irq_edt.Set_Focus();
}
}
display = REDRAW_BUTTONS;
break;
#endif //EDIT_IRQ
case (BUTTON_BAUD | KN_BUTTON):
item = (char *)baudlist.Current_Item();
strncpy( baudbuf, item, BAUDBUF_MAX );
baud_edt.Set_Text( baudbuf, BAUDBUF_MAX );
initstr_edt.Set_Focus();
initstr_edt.Flag_To_Redraw();
display = REDRAW_BUTTONS;
break;
case (BUTTON_BAUDLIST | KN_BUTTON):
if (baudlist.Current_Index() != baud_index) {
baud_index = baudlist.Current_Index();
item = (char *)baudlist.Current_Item();
strncpy( baudbuf, item, BAUDBUF_MAX );
baud_edt.Set_Text( baudbuf, BAUDBUF_MAX );
baud_edt.Clear_Focus();
display = REDRAW_BUTTONS;
}
break;
#if 0
case (BUTTON_INITSTR | KN_BUTTON):
strupr( initstrbuf );
strncpy( InitStrings[ initstr_index ], initstrbuf, INITSTRBUF_MAX );
Build_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,
&initstr_index);
cwaitstr_edt.Set_Focus();
cwaitstr_edt.Flag_To_Redraw();
display = REDRAW_BUTTONS;
break;
#endif
case (BUTTON_INITSTRLIST | KN_BUTTON):
if (initstrlist.Current_Index() != initstr_index) {
initstr_index = initstrlist.Current_Index();
item = (char *)initstrlist.Current_Item();
strncpy( initstrbuf, item, INITSTRBUF_MAX );
initstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );
}
initstr_edt.Set_Focus();
initstr_edt.Flag_To_Redraw();
display = REDRAW_BUTTONS;
break;
/*------------------------------------------------------------------
Add a new InitString entry
------------------------------------------------------------------*/
case (BUTTON_ADD | KN_BUTTON):
item = new char[ INITSTRBUF_MAX ];
memset (item, 0, INITSTRBUF_MAX);
strupr ( initstrbuf );
strncpy ( item, initstrbuf, INITSTRBUF_MAX-1 );
InitStrings.Add ( item );
Build_Init_String_Listbox (&initstrlist, &initstr_edt, initstrbuf,
&initstr_index);
/*............................................................
Set the current listbox index to the newly-added item.
............................................................*/
for (i = 0; i < InitStrings.Count(); i++) {
if (item == InitStrings[i]) {
initstr_index = i;
strcpy( initstrbuf, InitStrings[ initstr_index ] );
initstr_edt.Set_Text( initstrbuf, INITSTRBUF_MAX );
initstrlist.Set_Selected_Index( initstr_index );
}
}
initstr_edt.Set_Focus();
initstr_edt.Flag_To_Redraw();
display = REDRAW_BUTTONS;
break;
/*------------------------------------------------------------------
Delete the current InitString entry
------------------------------------------------------------------*/
case (BUTTON_DELETE | KN_BUTTON):
if ( InitStrings.Count() && initstr_index != -1) {
InitStrings.Delete( initstr_index );
Build_Init_String_Listbox(&initstrlist, &initstr_edt, initstrbuf,
&initstr_index);
}
break;
case (BUTTON_CWAITSTR | KN_BUTTON):
item = (char *)cwaitstrlist.Current_Item();
if (cwaitstr_index < 3) {
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
len = strlen( cwaitstrbuf );
strncpy( item + pos, cwaitstrbuf, len );
*(item + pos + len) = 0;
display = REDRAW_BUTTONS;
}
}
break;
case (BUTTON_CWAITSTRLIST | KN_BUTTON):
if (cwaitstrlist.Current_Index() != cwaitstr_index) {
cwaitstr_index = cwaitstrlist.Current_Index();
item = (char *)cwaitstrlist.Current_Item();
if (cwaitstr_index < 3) {
strncpy( cwaitstrbuf, item, CWAITSTRBUF_MAX );
cwaitstr_edt.Clear_Focus();
} else {
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
strncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );
}
cwaitstr_edt.Set_Focus();
}
cwaitstr_edt.Set_Text( cwaitstrbuf, CWAITSTRBUF_MAX );
} else {
if (cwaitstr_index < 3) {
cwaitstr_edt.Clear_Focus();
} else {
cwaitstr_edt.Set_Focus();
}
}
display = REDRAW_BUTTONS;
break;
case (BUTTON_TONE | KN_BUTTON):
tempsettings.DialMethod = DIAL_TOUCH_TONE;
tonebtn.Turn_On();
pulsebtn.Turn_Off();
break;
case (BUTTON_PULSE | KN_BUTTON):
tempsettings.DialMethod = DIAL_PULSE;
tonebtn.Turn_Off();
pulsebtn.Turn_On();
break;
/*------------------------------------------------------------------
SAVE: save the com settings
------------------------------------------------------------------*/
case (KN_RETURN):
case (BUTTON_SAVE | KN_BUTTON):
switch (port_index) {
case ( 0 ):
tempsettings.Port = 0x3f8;
break;
case ( 1 ):
tempsettings.Port = 0x2f8;
break;
case ( 2 ):
tempsettings.Port = 0x3e8;
break;
case ( 3 ):
tempsettings.Port = 0x2e8;
break;
default:
sscanf( portbuf, "%x", &tempsettings.Port );
break;
}
#ifdef EDIT_IRQ
switch (irq_index) {
case ( 0 ):
tempsettings.IRQ = 2;
break;
case ( 1 ):
tempsettings.IRQ = 3;
break;
case ( 2 ):
tempsettings.IRQ = 4;
break;
case ( 3 ):
tempsettings.IRQ = 5;
break;
default:
sscanf( irqbuf, "%d", &tempsettings.IRQ );
break;
}
#endif //EDIT_IRQ
sscanf( baudbuf, "%d", &tempsettings.Baud );
tempsettings.InitStringIndex = initstr_index;
tempsettings.CallWaitStringIndex = cwaitstr_index;
item = CallWaitStrings[ CALL_WAIT_CUSTOM ];
temp = strchr( item, '-' );
if ( temp ) {
pos = (int)(temp - item) + 2;
strncpy( cwaitstrbuf, item + pos, CWAITSTRBUF_MAX );
} else {
cwaitstrbuf[ 0 ] = 0;
}
strncpy( tempsettings.CallWaitString, cwaitstrbuf, CWAITSTRBUF_MAX );
dpstatus = NullModem.Detect_Port( &tempsettings );
if (dpstatus == PORT_VALID) {
process = false;
rc = true;
}
else if (dpstatus == PORT_INVALID) {
CCMessageBox().Process( TXT_INVALID_SETTINGS );
firsttime = 1;
display = REDRAW_ALL;
}
else if (dpstatus == PORT_IRQ_INUSE) {
CCMessageBox().Process( TXT_IRQ_ALREADY_IN_USE );
firsttime = 1;
display = REDRAW_ALL;
}
break;
/*------------------------------------------------------------------
CANCEL: send a SIGN_OFF, bail out with error code
------------------------------------------------------------------*/
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
}
} /* end of while */
/*------------------------------------------------------------------------
Restore screen
------------------------------------------------------------------------*/
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Show_Mouse();
/*------------------------------------------------------------------------
Save values into the Settings structure
------------------------------------------------------------------------*/
if (rc) {
memcpy( settings, &tempsettings, sizeof(SerialSettingsType) );
}
return(rc);
} /* end of Com_Settings_Dialog */
/***************************************************************************
* Build_Init_String_Listbox -- [re]builds the initstring listbox *
* *
* This routine rebuilds the initstring list box from scratch; it also *
* updates the contents of the initstring edit field. *
* *
* INPUT: *
* list ptr to list box *
* edit ptr to edit box *
* buf ptr to buffer for initstring *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 06/08/1995 DRD : Created. *
*=========================================================================*/
static void Build_Init_String_Listbox (ListClass *list, EditClass *edit, char *buf, int *index)
{
int i, curidx;
char *item;
curidx = *index;
/*........................................................................
Clear the list
........................................................................*/
while (list->Count()) {
item = (char *)(list->Get_Item(0));
list->Remove_Item(item);
delete [] item;
}
/*
** Now sort the init string list by name then number
*/
qsort ((void *)(&InitStrings[0]), InitStrings.Count(), sizeof(char *), Init_String_Compare);
/*........................................................................
Build the list
........................................................................*/
for (i = 0; i < InitStrings.Count(); i++) {
item = new char[ INITSTRBUF_MAX ];
strcpy( item, InitStrings[i] );
list->Add_Item(item);
}
list->Flag_To_Redraw();
/*........................................................................
Init the current phone book index
........................................................................*/
if (list->Count() == 0 || curidx < -1) {
curidx = -1;
} else {
if (curidx >= list->Count() ) {
curidx = 0;
}
}
/*........................................................................
Fill in initstring edit buffer
........................................................................*/
if (curidx > -1) {
strcpy (buf, InitStrings[ curidx ]);
edit->Set_Text (buf, INITSTRBUF_MAX );
list->Set_Selected_Index( curidx );
}
*index = curidx;
}
/***************************************************************************
* Init_String_Compare -- for qsort *
* *
* INPUT: *
* p1,p2 ptrs to elements to compare *
* *
* OUTPUT: *
* 0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2) *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 06/08/1995 DRD : Created. *
*=========================================================================*/
static int Init_String_Compare (const void *p1, const void *p2)
{
return( strcmp( *((char **)p1), *((char **)p2) ) );
}
/***********************************************************************************************
* Com_Scenario_Dialog -- Serial game scenario selection dialog *
* *
* *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ *
* <20> Serial Game <20> *
* <20> <20> *
* <20> Your Name: __________ House: [GDI] [NOD] <20> *
* <20> Credits: ______ Desired Color: [ ][ ][ ][ ] <20> *
* <20> Opponent: Name <20> *
* <20> <20> *
* <20> Scenario <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> *
* <20> <20> Hell's Kitchen <20><18> <20> *
* <20> <20> Heaven's Gate <20>Ĵ <20> *
* <20> <20> ... <20> <20> <20> *
* <20> <20> <20>Ĵ <20> *
* <20> <20> <20><19> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> [ Bases ] [ Crates ] <20> *
* <20> [ Tiberium ] [ AI Players ] <20> *
* <20> <20> *
* <20> [OK] [Cancel] <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> *
* <20> <20> <20> <20> *
* <20> <20> <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> [Send Message] <20> *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* true = success, false = cancel *
* *
* WARNINGS: *
* MPlayerName & MPlayerGameName must contain this player's name. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
#define TXT_HOST_INTERNET_GAME 4567+1
#define TXT_JOIN_INTERNET_GAME 4567+2
int Com_Scenario_Dialog(void)
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 290*factor; // dialog width
int d_dialog_h = 190*factor; // dialog height
int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
int d_dialog_y = ((200*factor - d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 6*factor+1; // ht of 6-pt text
int d_margin1 = 5*factor; // margin width/height
int d_margin2 = 2*factor; // margin width/height
int d_name_w = 70*factor;
int d_name_h = 9*factor;
int d_name_x = d_dialog_x + 108*factor;
int d_name_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h + d_margin1;
int d_credits_w = ((CREDITSBUF_MAX - 1) * 6*factor) + 3*factor;
int d_credits_h = 9*factor;
int d_credits_x = d_name_x;
int d_credits_y = d_name_y + d_name_h + d_margin2;
int d_gdi_w = 30*factor;
int d_gdi_h = 9*factor;
int d_gdi_x = d_dialog_cx + (d_dialog_w / 4);
int d_gdi_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h + d_margin1;
int d_nod_w = 30*factor;
int d_nod_h = 9*factor;
int d_nod_x = d_gdi_x + d_gdi_w + (d_margin1 / 2);
int d_nod_y = d_gdi_y;
int d_color_w = 10*factor;
int d_color_h = 9*factor;
int d_color_y = d_gdi_y + d_gdi_h + d_margin2;
int d_opponent_x = d_name_x;
int d_opponent_y = d_color_y + d_color_h + d_margin2;
int d_scenariolist_w = 182*factor;
int d_scenariolist_h = 27*factor;
int d_scenariolist_x = d_dialog_cx - (d_scenariolist_w / 2);
int d_scenariolist_y = d_opponent_y + d_txt6_h + 3*factor + d_txt6_h;
// d_count_x is calculated below after other enums
int d_count_w = 25*factor;
int d_count_h = 7*factor;
int d_count_y = d_scenariolist_y + d_scenariolist_h + d_margin2;
// d_level_x is calculated below after other enums
int d_level_w = 25*factor;
int d_level_h = 7*factor;
int d_level_y = d_count_y;
#if (GERMAN | FRENCH)
int d_bases_w = 120*factor;//BGA:100;
#else
int d_bases_w = 110*factor;
#endif
int d_bases_h = 9*factor;
int d_bases_x = d_dialog_cx - d_bases_w - d_margin2;
int d_bases_y = d_count_y + d_count_h + d_margin2;
#if (GERMAN | FRENCH)
int d_goodies_w = 120*factor;
#else
int d_goodies_w = 110*factor;
#endif
int d_goodies_h = 9*factor;
int d_goodies_x = d_dialog_cx + d_margin2;
int d_goodies_y = d_bases_y;
int d_count_x = d_dialog_cx - d_count_w - ((2 * 6*factor) + 3*factor)
- ((d_bases_w - ((13 * 6*factor) + 3*factor + d_count_w)) / 2) - d_margin2;
int d_level_x = d_dialog_cx + (11 * 6*factor)
+ ((d_goodies_w - ((13 * 6*factor) + 3*factor + d_level_w)) / 2) + d_margin2;
#if (GERMAN | FRENCH)
int d_tiberium_w = 120*factor;
#else
int d_tiberium_w = 110*factor;
#endif
int d_tiberium_h = 9*factor;
int d_tiberium_x = d_dialog_cx - d_bases_w - d_margin2;
int d_tiberium_y = d_bases_y + d_bases_h + d_margin2;
#if (GERMAN | FRENCH)
int d_ghosts_w = 120*factor;
#else
int d_ghosts_w = 110*factor;
#endif
int d_ghosts_h = 9*factor;
int d_ghosts_x = d_dialog_cx + d_margin2;
int d_ghosts_y = d_tiberium_y;
int d_ok_w = 45*factor;
int d_ok_h = 9*factor;
int d_ok_x = d_tiberium_x + (d_tiberium_w / 2) - (d_ok_w / 2);
int d_ok_y = d_tiberium_y + d_tiberium_h + d_margin1;
int d_cancel_w = 45*factor;
int d_cancel_h = 9*factor;
int d_cancel_x = d_ghosts_x + (d_ghosts_w / 2) - (d_cancel_w / 2);
int d_cancel_y = d_tiberium_y + d_tiberium_h + d_margin1;
int d_message_w = d_dialog_w - (d_margin1 * 2);
int d_message_h = 34*factor;
int d_message_x = d_dialog_x + d_margin1;
int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
int d_send_w = 80*factor;
int d_send_h = 9*factor;
int d_send_x = d_dialog_cx - (d_send_w / 2);
int d_send_y = d_message_y + d_message_h + d_margin2;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_NAME = 100,
BUTTON_GDI,
BUTTON_NOD,
BUTTON_CREDITS,
BUTTON_SCENARIOLIST,
BUTTON_COUNT,
BUTTON_LEVEL,
BUTTON_BASES,
BUTTON_TIBERIUM,
BUTTON_GOODIES,
BUTTON_GHOSTS,
BUTTON_OK,
BUTTON_CANCEL,
BUTTON_SEND,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_MESSAGE,
REDRAW_COLORS,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
bool process = true; // process while true
KeyNumType input;
char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
char credbuf[CREDITSBUF_MAX]; // for credit edit box
int old_cred; // old value in credits buffer
int transmit; // 1 = re-transmit new game options
int cbox_x[] = { d_gdi_x,
d_gdi_x + d_color_w,
d_gdi_x + (d_color_w * 2),
d_gdi_x + (d_color_w * 3),
d_gdi_x + (d_color_w * 4),
d_gdi_x + (d_color_w * 5)};
int parms_received = 0; // 1 = game options received
int changed = 0; // 1 = user has changed an option
int rc;
int recsignedoff = false;
int i;
int version;
char txt[80];
unsigned long starttime;
unsigned long timingtime;
unsigned long lastmsgtime;
unsigned long lastredrawtime;
unsigned long transmittime = 0;
unsigned long theirresponsetime;
int packetlen;
static int first_time = 1;
bool oppscorescreen = false;
bool gameoptions = false;
EventClass *event; // event ptr
unsigned long msg_timeout = 1200; // init to 20 seconds
int message_length;
int sent_so_far;
unsigned short magic_number;
unsigned short crc;
void const *up_button;
void const *down_button;
if (InMainLoop){
up_button = Hires_Retrieve("BTN-UP.SHP");
down_button = Hires_Retrieve("BTN-DN.SHP");
}else{
up_button = Hires_Retrieve("BTN-UP2.SHP");
down_button = Hires_Retrieve("BTN-DN2.SHP");
}
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
EditClass name_edt (BUTTON_NAME,
namebuf, MPLAYER_NAME_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
TextButtonClass gdibtn(BUTTON_GDI, TXT_G_D_I,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);
TextButtonClass nodbtn(BUTTON_NOD, TXT_N_O_D,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_nod_x, d_nod_y, d_nod_w, d_nod_h);
EditClass credit_edt (BUTTON_CREDITS,
credbuf, CREDITSBUF_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_credits_x, d_credits_y, d_credits_w, d_credits_h, EditClass::ALPHANUMERIC);
ListClass scenariolist(BUTTON_SCENARIOLIST,
d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
GaugeClass countgauge (BUTTON_COUNT,
d_count_x, d_count_y, d_count_w, d_count_h);
GaugeClass levelgauge (BUTTON_LEVEL,
d_level_x, d_level_y, d_level_w, d_level_h);
TextButtonClass basesbtn(BUTTON_BASES, TXT_BASES_OFF,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_bases_x, d_bases_y, d_bases_w, d_bases_h);
TextButtonClass tiberiumbtn(BUTTON_TIBERIUM, TXT_TIBERIUM_OFF,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_tiberium_x, d_tiberium_y, d_tiberium_w, d_tiberium_h);
TextButtonClass goodiesbtn(BUTTON_GOODIES, TXT_CRATES_OFF,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_goodies_x, d_goodies_y, d_goodies_w, d_goodies_h);
TextButtonClass ghostsbtn(BUTTON_GHOSTS, TXT_AI_PLAYERS_OFF,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_ghosts_x, d_ghosts_y, d_ghosts_w, d_ghosts_h);
TextButtonClass okbtn(BUTTON_OK, TXT_OK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_ok_x, d_ok_y, d_ok_w, d_ok_h);
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_cancel_x, d_cancel_y);
#else
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
#endif
TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_send_x, d_send_y);
#else
d_send_x, d_send_y, d_send_w, d_send_h);
#endif
/*
------------------------- Build the button list --------------------------
*/
commands = &name_edt;
gdibtn.Add_Tail(*commands);
nodbtn.Add_Tail(*commands);
credit_edt.Add_Tail(*commands);
scenariolist.Add_Tail(*commands);
countgauge.Add_Tail(*commands);
levelgauge.Add_Tail(*commands);
basesbtn.Add_Tail(*commands);
tiberiumbtn.Add_Tail(*commands);
goodiesbtn.Add_Tail(*commands);
ghostsbtn.Add_Tail(*commands);
okbtn.Add_Tail(*commands);
cancelbtn.Add_Tail(*commands);
sendbtn.Add_Tail(*commands);
/*
----------------------------- Various Inits ------------------------------
*/
/*........................................................................
Init player name & house
........................................................................*/
MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
strcpy (namebuf, MPlayerName); // set my name
name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
name_edt.Set_Color(MPlayerTColors[MPlayerColorIdx]);
if (MPlayerHouse==HOUSE_GOOD) {
gdibtn.Turn_On();
} else {
nodbtn.Turn_On();
}
/*........................................................................
Init scenario values, only the first time through
........................................................................*/
if (first_time) {
MPlayerCredits = 3000; // init credits & credit buffer
MPlayerBases = 1; // init scenario parameters
MPlayerTiberium = 0;
MPlayerGoodies = 0;
MPlayerGhosts = 0;
Special.IsCaptureTheFlag = 0;
MPlayerUnitCount = (MPlayerCountMax[MPlayerBases] + MPlayerCountMin[MPlayerBases]) / 2;
first_time = 0;
}
/*........................................................................
Init button states
........................................................................*/
if (MPlayerBases) {
basesbtn.Turn_On();
basesbtn.Set_Text(TXT_BASES_ON);
}
if (MPlayerTiberium) {
tiberiumbtn.Turn_On();
tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
}
if (MPlayerGoodies) {
goodiesbtn.Turn_On();
goodiesbtn.Set_Text(TXT_CRATES_ON);
}
if (MPlayerGhosts) {
ghostsbtn.Turn_On();
ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
}
if (Special.IsCaptureTheFlag) {
MPlayerGhosts = 0;
ghostsbtn.Turn_On();
ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
}
sprintf(credbuf, "%d", MPlayerCredits);
credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
old_cred = MPlayerCredits;
levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
levelgauge.Set_Value(BuildLevel - 1);
countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
/*........................................................................
Init other scenario parameters
........................................................................*/
Special.IsTGrowth = MPlayerTiberium;
Special.IsTSpread = MPlayerTiberium;
transmit = 1;
/*........................................................................
Init scenario description list box
........................................................................*/
for (i = 0; i < MPlayerScenarios.Count(); i++) {
scenariolist.Add_Item (strupr(MPlayerScenarios[i]));
}
ScenarioIdx = 0; // 1st scenario is selected
/*........................................................................
Init random-number generator, & create a seed to be used for all random
numbers from here on out
........................................................................*/
randomize();
Seed = rand();
/*........................................................................
Init the message display system
........................................................................*/
Messages.Init (d_message_x + 2*factor, d_message_y + 2*factor, 4, MAX_MESSAGE_LENGTH, d_txt6_h);
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
extern char ModemRXString[];
if (strlen(ModemRXString) > 36)
ModemRXString[36] = 0;
if (strlen(ModemRXString) > 0)
Messages.Add_Message (ModemRXString, CC_TAN,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, 0, 0);
ModemRXString[0] = '\0';
/*
---------------------------- Init Mono Output ----------------------------
*/
#if(SHOW_MONO)
NullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),
SerialPacketNames, 106);
NullModem.Mono_Debug_Print(1);
#endif
/*
---------------------------- Processing loop -----------------------------
*/
NullModem.Reset_Response_Time(); // clear response time
theirresponsetime = 10000; // initialize to an invalid value
timingtime = lastmsgtime = lastredrawtime = TickCount.Time();
while (Get_Mouse_State() > 0) Show_Mouse();
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
if (display >= REDRAW_BACKGROUND) {
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
// init font variables
Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*...............................................................
Dialog & Field labels
...............................................................*/
#ifdef FORCE_WINSOCK
if (Winsock.Get_Connected()){
Draw_Caption (TXT_HOST_INTERNET_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}else{
Draw_Caption (TXT_HOST_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}
#else
Draw_Caption (TXT_HOST_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
#endif //FORCE_WINSOCK
Fancy_Text_Print(TXT_YOUR_NAME,
d_name_x - 5*factor, d_name_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print(TXT_SIDE_COLON,
d_gdi_x - 5*factor, d_gdi_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print (TXT_START_CREDITS_COLON, d_credits_x - 5*factor, d_credits_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print(TXT_COLOR_COLON,
cbox_x[0] - 5*factor, d_color_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print(TXT_SCENARIOS,
d_scenariolist_x + (d_scenariolist_w / 2),
d_scenariolist_y - d_txt6_h,
CC_GREEN, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print (TXT_COUNT, d_count_x - 3*factor, d_count_y, CC_GREEN, TBLACK,
TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
Fancy_Text_Print (TXT_LEVEL, d_level_x - 3*factor, d_level_y, CC_GREEN, TBLACK,
TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
}
/*..................................................................
Draw the color boxes
..................................................................*/
if (display >= REDRAW_COLORS) {
for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
LogicPage->Fill_Rect (cbox_x[i] + 1*factor, d_color_y + 1*factor,
cbox_x[i] + 1*factor + d_color_w - 2*factor, d_color_y + 1*factor + d_color_h - 2*factor,
MPlayerGColors[i]);
if (i == MPlayerColorIdx) {
Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
BOXSTYLE_GREEN_DOWN, false);
} else {
Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
BOXSTYLE_GREEN_RAISED, false);
}
}
}
/*..................................................................
Draw the message:
- Erase an old message first
..................................................................*/
if (display >= REDRAW_MESSAGE) {
Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
BOXSTYLE_GREEN_BORDER, true);
Messages.Draw();
LogicPage->Fill_Rect (d_dialog_x + 2*factor,
d_opponent_y,
d_dialog_x + d_dialog_w - 4*factor,
d_opponent_y + d_txt6_h,
BLACK);
if (parms_received) {
if (oppscorescreen) {
sprintf(txt,"%s",Text_String(TXT_WAITING_FOR_OPPONENT));
int txtwidth = String_Pixel_Width( txt );
Fancy_Text_Print (txt, d_dialog_cx - (txtwidth / 2),
d_opponent_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
} else {
Fancy_Text_Print (TXT_OPPONENT_COLON, d_opponent_x - 3*factor,
d_opponent_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (TheirHouse == HOUSE_GOOD) {
sprintf(txt,"%s %s",TheirName,Text_String(TXT_G_D_I));
} else {
sprintf(txt,"%s %s",TheirName,Text_String(TXT_N_O_D));
}
Fancy_Text_Print (txt, d_opponent_x,
d_opponent_y, MPlayerTColors[TheirColor], TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
}
sprintf( txt, "%d ", MPlayerUnitCount );
Fancy_Text_Print (txt, d_count_x + d_count_w + 3*factor,
d_count_y, CC_GREEN, BLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
sprintf(txt, "%d ", BuildLevel);
} else {
sprintf(txt, "**");
}
Fancy_Text_Print (txt, d_level_x + d_level_w + 3*factor,
d_level_y, CC_GREEN, BLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
commands->Flag_List_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
---------------------------- Process input ----------------------------
*/
switch (input) {
/*------------------------------------------------------------------
User clicks on a color button
------------------------------------------------------------------*/
case KN_LMOUSE:
if (_Kbd->MouseQX > cbox_x[0] &&
_Kbd->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
_Kbd->MouseQY > d_color_y &&
_Kbd->MouseQY < (d_color_y + d_color_h)) {
MPlayerPrefColor = (_Kbd->MouseQX - cbox_x[0]) / d_color_w;
MPlayerColorIdx = MPlayerPrefColor;
display = REDRAW_COLORS;
name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
name_edt.Flag_To_Redraw();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
changed = 1;
}
break;
/*------------------------------------------------------------------
User edits the name field; retransmit new game options
------------------------------------------------------------------*/
case (BUTTON_NAME | KN_BUTTON):
credit_edt.Clear_Focus();
credit_edt.Flag_To_Redraw();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
changed = 1;
break;
/*------------------------------------------------------------------
House Buttons: set the player's desired House
------------------------------------------------------------------*/
case (BUTTON_GDI | KN_BUTTON):
MPlayerHouse = HOUSE_GOOD;
gdibtn.Turn_On();
nodbtn.Turn_Off();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
case (BUTTON_NOD | KN_BUTTON):
MPlayerHouse = HOUSE_BAD;
gdibtn.Turn_Off();
nodbtn.Turn_On();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
User edits the credits value; retransmit new game options
------------------------------------------------------------------*/
case (BUTTON_CREDITS | KN_BUTTON):
name_edt.Clear_Focus();
name_edt.Flag_To_Redraw();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
New Scenario selected.
------------------------------------------------------------------*/
case (BUTTON_SCENARIOLIST | KN_BUTTON):
if (scenariolist.Current_Index() != ScenarioIdx) {
ScenarioIdx = scenariolist.Current_Index();
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
}
break;
/*------------------------------------------------------------------
User adjusts max # units
------------------------------------------------------------------*/
case (BUTTON_COUNT | KN_BUTTON):
MPlayerUnitCount = countgauge.Get_Value() + MPlayerCountMin[MPlayerBases];
display = REDRAW_MESSAGE;
transmit = 1;
break;
/*------------------------------------------------------------------
User adjusts build level
------------------------------------------------------------------*/
case (BUTTON_LEVEL | KN_BUTTON):
BuildLevel = levelgauge.Get_Value() + 1;
if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out
BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
display = REDRAW_MESSAGE;
transmit = 1;
break;
/*------------------------------------------------------------------
Toggle bases
------------------------------------------------------------------*/
case (BUTTON_BASES | KN_BUTTON):
if (MPlayerBases) {
MPlayerBases = 0;
basesbtn.Turn_Off();
basesbtn.Set_Text(TXT_BASES_OFF);
MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[0]-MPlayerCountMin[0],
Cardinal_To_Fixed(MPlayerCountMax[1]-MPlayerCountMin[1],
MPlayerUnitCount-MPlayerCountMin[1])) + MPlayerCountMin[0];
} else {
MPlayerBases = 1;
basesbtn.Turn_On();
basesbtn.Set_Text(TXT_BASES_ON);
MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[1]-MPlayerCountMin[1],
Cardinal_To_Fixed(MPlayerCountMax[0]-MPlayerCountMin[0],
MPlayerUnitCount-MPlayerCountMin[0])) + MPlayerCountMin[1];
}
MPlayerCredits = atoi(credbuf);
countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
strcpy (MPlayerName, namebuf);
transmit = 1;
display = REDRAW_ALL;
break;
/*------------------------------------------------------------------
Toggle tiberium
------------------------------------------------------------------*/
case (BUTTON_TIBERIUM | KN_BUTTON):
if (MPlayerTiberium) {
MPlayerTiberium = 0;
Special.IsTGrowth = 0;
Special.IsTSpread = 0;
tiberiumbtn.Turn_Off();
tiberiumbtn.Set_Text(TXT_TIBERIUM_OFF);
} else {
MPlayerTiberium = 1;
Special.IsTGrowth = 1;
Special.IsTSpread = 1;
tiberiumbtn.Turn_On();
tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
}
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
Toggle goodies
------------------------------------------------------------------*/
case (BUTTON_GOODIES | KN_BUTTON):
if (MPlayerGoodies) {
MPlayerGoodies = 0;
goodiesbtn.Turn_Off();
goodiesbtn.Set_Text(TXT_CRATES_OFF);
} else {
MPlayerGoodies = 1;
goodiesbtn.Turn_On();
goodiesbtn.Set_Text(TXT_CRATES_ON);
}
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
Toggle ghosts
------------------------------------------------------------------*/
case (BUTTON_GHOSTS | KN_BUTTON):
if (!MPlayerGhosts && !Special.IsCaptureTheFlag) { // ghosts OFF => ghosts ON
MPlayerGhosts = 1;
Special.IsCaptureTheFlag = 0;
ghostsbtn.Turn_On();
ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
}
else if (MPlayerGhosts) { // ghosts ON => capture-flag
MPlayerGhosts = 0;
Special.IsCaptureTheFlag = 1;
ghostsbtn.Turn_On();
ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
}
else if (Special.IsCaptureTheFlag) { // capture-flag => AI OFF
MPlayerGhosts = 0;
Special.IsCaptureTheFlag = 0;
ghostsbtn.Turn_Off();
ghostsbtn.Set_Text(TXT_AI_PLAYERS_OFF);
}
MPlayerCredits = atoi(credbuf);
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
OK: exit loop with true status
------------------------------------------------------------------*/
case (BUTTON_OK | KN_BUTTON):
//
// make sure we got a game options packet from the other player
//
if (gameoptions) {
rc = true;
process = false;
// force transmitting of game options packet one last time
transmit = 1;
transmittime = 0;
} else {
CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
display = REDRAW_ALL;
}
break;
/*------------------------------------------------------------------
CANCEL: send a SIGN_OFF, bail out with error code
------------------------------------------------------------------*/
case (KN_ESC):
if (Messages.Get_Edit_Buf() != NULL) {
Messages.Input(input);
display = REDRAW_MESSAGE;
break;
}
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
/*------------------------------------------------------------------
Default: manage the inter-player messages
------------------------------------------------------------------*/
default:
/*...............................................................
F4/SEND/'M' = send a message
...............................................................*/
if (Messages.Get_Edit_Buf()==NULL) {
if (input == KN_M || input==(BUTTON_SEND | KN_BUTTON) ||
input == KN_F4) {
memset (txt, 0, 80);
strcpy(txt,Text_String(TXT_MESSAGE)); // "Message:"
Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
display = REDRAW_MESSAGE;
credit_edt.Clear_Focus();
credit_edt.Flag_To_Redraw();
name_edt.Clear_Focus();
name_edt.Flag_To_Redraw();
break;
}
} else {
if ( input == (BUTTON_SEND | KN_BUTTON) ) {
input = KN_RETURN;
}
}
/*...............................................................
Manage the message system (get rid of old messages)
...............................................................*/
if (Messages.Manage()) {
display = REDRAW_MESSAGE;
}
/*...............................................................
Service keyboard input for any message being edited.
...............................................................*/
i = Messages.Input(input);
/*...............................................................
If 'Input' returned 1, it means refresh the message display.
...............................................................*/
if (i==1) {
Messages.Draw();
}
/*...............................................................
If 'Input' returned 2, it means redraw the message display.
...............................................................*/
else if (i==2) {
display = REDRAW_MESSAGE;
}
/*...............................................................
If 'input' returned 3, it means send the current message.
...............................................................*/
else if (i==3) {
sent_so_far = 0;
magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
message_length = strlen(Messages.Get_Edit_Buf());
crc = (unsigned short)
(Calculate_CRC(Messages.Get_Edit_Buf(), message_length) &0xffff);
while (sent_so_far < message_length){
SendPacket.Command = SERIAL_MESSAGE;
strcpy (SendPacket.Name, MPlayerName);
SendPacket.ID = Build_MPlayerID(MPlayerColorIdx, MPlayerHouse);
memcpy (SendPacket.Message, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
*(SendPacket.Message + COMPAT_MESSAGE_LENGTH-5) = 0;
*((unsigned short*)(SendPacket.Message + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
*((unsigned short*)(SendPacket.Message + COMPAT_MESSAGE_LENGTH-2)) = crc;
/*..................................................................
Send the message
..................................................................*/
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
NullModem.Service();
/*..................................................................
Add the message to our own screen
..................................................................*/
sprintf(txt, Text_String (TXT_FROM), MPlayerName, SendPacket.Message);
Messages.Add_Message (txt, MPlayerTColors[MPlayerColorIdx],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
magic_number++;
sent_so_far += COMPAT_MESSAGE_LENGTH-5;
}
display = REDRAW_MESSAGE;
} /* end of send message */
} /* end of input processing */
/*---------------------------------------------------------------------
Detect editing of the credits buffer, transmit new values to players
---------------------------------------------------------------------*/
if (atoi(credbuf) != old_cred) {
old_cred = Bound(atoi(credbuf), 0, 9999);
MPlayerCredits = old_cred;
transmit = 1;
sprintf(credbuf, "%d", MPlayerCredits);
credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
}
/*---------------------------------------------------------------------
Detect editing of the name buffer, transmit new values to players
---------------------------------------------------------------------*/
if (strcmp (namebuf, MPlayerName)) {
strcpy (MPlayerName, namebuf);
transmit = 1;
changed = 1;
}
/*---------------------------------------------------------------------
If our Transmit flag is set, we need to send out a game option packet.
This message requires an ACK. The first time through the loop, transmit
should be set, so we send out our default options; we'll then send
any changes we make to the defaults.
---------------------------------------------------------------------*/
if (transmit && (TickCount.Time() - transmittime) > PACKET_RETRANS_TIME) {
SendPacket.Command = SERIAL_GAME_OPTIONS;
strcpy (SendPacket.Name, MPlayerName);
#ifdef PATCH
if (IsV107) {
SendPacket.Version = 1;
} else {
SendPacket.Version = 2;
}
#else
SendPacket.Version = Version_Number();
#endif
SendPacket.House = MPlayerHouse;
SendPacket.Color = MPlayerColorIdx;
SendPacket.Scenario = MPlayerFilenum[ScenarioIdx];
SendPacket.Credits = MPlayerCredits;
SendPacket.IsBases = MPlayerBases;
SendPacket.IsTiberium = MPlayerTiberium;
SendPacket.IsGoodies = MPlayerGoodies;
SendPacket.IsGhosties = MPlayerGhosts;
SendPacket.BuildLevel = BuildLevel;
SendPacket.UnitCount = MPlayerUnitCount;
SendPacket.Seed = Seed;
SendPacket.Special = Special;
SendPacket.GameSpeed = Options.GameSpeed;
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
transmittime = TickCount.Time();
transmit = 0;
}
//
// send a timing packet if enough time has gone by.
//
if ( (TickCount.Time() - timingtime) > PACKET_TIMING_TIMEOUT) {
SendPacket.Command = SERIAL_TIMING;
SendPacket.ResponseTime = NullModem.Response_Time();
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);
timingtime = TickCount.Time();
}
/*---------------------------------------------------------------------
Check for an incoming message
---------------------------------------------------------------------*/
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
// Smart_Printf( "received packet of length %d\n", packetlen );
lastmsgtime = TickCount.Time();
msg_timeout = 600; // reset timeout value to 10 seconds
// (only the 1st time through is 20 seconds)
// are we getting our own packets back??
if (ReceivePacket.Command >= SERIAL_CONNECT &&
ReceivePacket.Command < SERIAL_LAST_COMMAND &&
ReceivePacket.Command != SERIAL_MESSAGE &&
ReceivePacket.ID == ModemGameToPlay) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
break;
}
event = (EventClass *)&ReceivePacket;
if (event->Type <= EventClass::FRAMEINFO) {
if ( (TickCount.Time() - lastredrawtime) > PACKET_REDRAW_TIME) {
lastredrawtime = TickCount.Time();
oppscorescreen = true;
if (display != REDRAW_ALL) {
display = REDRAW_MESSAGE;
}
// display = REDRAW_MESSAGE;
parms_received = 1;
}
} else {
switch ( ReceivePacket.Command ) {
/*..................................................................
Sign-off: Give the other machine time to receive my ACK, display a
message, and exit.
..................................................................*/
case (SERIAL_SIGN_OFF):
// Smart_Printf( "received sign off\n" );
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 60)
NullModem.Service();
CCMessageBox().Process(TXT_USER_SIGNED_OFF);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
recsignedoff = true;
break;
/*..................................................................
Game Options: Store the other machine's name, color & house;
If they've picked the same color as myself, re-transmit my settings
to force him to choose a different color. (Com_Show_Scenario_Dialog
is responsible for ensuring the colors are different.)
..................................................................*/
case (SERIAL_GAME_OPTIONS):
// Smart_Printf( "received game options\n" );
oppscorescreen = false;
gameoptions = true;
strcpy (TheirName, ReceivePacket.Name);
TheirColor = ReceivePacket.Color;
TheirHouse = ReceivePacket.House;
transmit = 1;
parms_received = 1;
if (display != REDRAW_ALL) {
display = REDRAW_MESSAGE;
}
// display = REDRAW_MESSAGE;
/*...............................................................
Check the version number of the other system.
...............................................................*/
#ifdef PATCH
if (IsV107) {
version = 1;
} else {
version = 2;
}
#else
version = Version_Number();
#endif
if (ReceivePacket.Version > version) {
CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
} else {
if (ReceivePacket.Version < version) {
CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
}
}
break;
/*..................................................................
Incoming message: add to our list
..................................................................*/
case (SERIAL_MESSAGE):
// Smart_Printf( "received serial message\n" );
oppscorescreen = false;
sprintf(txt, Text_String (TXT_FROM), ReceivePacket.Name,
ReceivePacket.Message);
magic_number = *((unsigned short*)(ReceivePacket.Message + COMPAT_MESSAGE_LENGTH-4));
crc = *((unsigned short*)(ReceivePacket.Message + COMPAT_MESSAGE_LENGTH-2));
Messages.Add_Message (txt,
MPlayerTColors[MPlayerID_To_ColorIndex(ReceivePacket.ID)],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
if (display != REDRAW_ALL) {
display = REDRAW_MESSAGE;
}
// display = REDRAW_MESSAGE;
break;
//
// get their response time
//
case (SERIAL_TIMING):
// Smart_Printf( "received timing\n" );
oppscorescreen = false;
theirresponsetime = ReceivePacket.ResponseTime;
if ( !gameoptions ) {
// retransmit of game options packet again
transmit = 1;
}
break;
//
// print msg waiting for opponent
//
case (SERIAL_SCORE_SCREEN):
// Smart_Printf( "received score screen\n" );
oppscorescreen = true;
if (display != REDRAW_ALL) {
display = REDRAW_MESSAGE;
}
// display = REDRAW_MESSAGE;
parms_received = 1;
break;
default:
// Smart_Printf( "received unknown command %X\n", ReceivePacket.Command );
break;
}
}
}
// if we haven't received a msg for 10 seconds exit
if ( (TickCount.Time() - lastmsgtime) > msg_timeout) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
}
/*---------------------------------------------------------------------
Service the connection
---------------------------------------------------------------------*/
NullModem.Service();
} /* end of while */
/*------------------------------------------------------------------------
Sort player ID's, so we can execute commands in the same order on both
machines.
------------------------------------------------------------------------*/
if (rc) {
/*.....................................................................
Set the number of players in this game, and my ID
.....................................................................*/
MPlayerCount = 2;
MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
TheirID = Build_MPlayerID (TheirColor,TheirHouse);
/*.....................................................................
Store every player's ID in the MPlayerID[] array. This array will
determine the order of event execution, so the ID's must be stored
in the same order on all systems.
.....................................................................*/
if (TheirID < MPlayerLocalID) {
MPlayerID[0] = TheirID;
MPlayerID[1] = MPlayerLocalID;
strcpy (MPlayerNames[0], TheirName);
strcpy (MPlayerNames[1], MPlayerName);
} else {
MPlayerID[0] = MPlayerLocalID;
MPlayerID[1] = TheirID;
strcpy (MPlayerNames[0], MPlayerName);
strcpy (MPlayerNames[1], TheirName);
}
/*.....................................................................
Get the scenario filename
.....................................................................*/
Scenario = MPlayerFilenum[ScenarioIdx];
/*.....................................................................
Send all players the GO packet.
.....................................................................*/
SendPacket.Command = SERIAL_GO;
SendPacket.ResponseTime = NullModem.Response_Time();
if ( theirresponsetime == 10000 ) {
// Mono_Clear_Screen();
// Smart_Printf( "Did not receive their response time!!!!!!!\n" );
// Get_Key();
} else {
if (SendPacket.ResponseTime < theirresponsetime) {
SendPacket.ResponseTime = theirresponsetime;
}
}
//
// calculated one way delay for a packet and overall delay to execute
// a packet
//
MPlayerMaxAhead = MAX( (SendPacket.ResponseTime / 8), 2);
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( ( NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_SENDING_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
NullModem.Service();
Keyboard::Check(); //Make sure the message loop gets called
}
// clear queue to keep from doing any resends
NullModem.Init_Send_Queue();
} else {
if ( !recsignedoff ) {
/*.....................................................................
Broadcast my sign-off over my network
.....................................................................*/
SendPacket.Command = SERIAL_SIGN_OFF;
SendPacket.Color = MPlayerLocalID; // use Color for ID
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( (NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_CANCEL_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {
// are we getting our own packets back??
if (ReceivePacket.Command == SERIAL_SIGN_OFF
&& ReceivePacket.ID == ModemGameToPlay) {
// exit while
break;
}
}
NullModem.Service();
}
}
Shutdown_Modem();
}
/*------------------------------------------------------------------------
Clear all lists
------------------------------------------------------------------------*/
while (scenariolist.Count()) {
scenariolist.Remove_Item(scenariolist.Get_Item(0));
}
/*------------------------------------------------------------------------
Restore screen
------------------------------------------------------------------------*/
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Show_Mouse();
/*------------------------------------------------------------------------
Save any changes made to our options
------------------------------------------------------------------------*/
if (changed) {
Write_MultiPlayer_Settings ();
}
return(rc);
} /* end of Com_Scenario_Dialog */
/***********************************************************************************************
* Com_Show_Scenario_Dialog -- Serial game scenario selection dialog *
* *
* *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ *
* <20> Serial Game <20> *
* <20> <20> *
* <20> Your Name: __________ <20> *
* <20> House: [GDI] [NOD] <20> *
* <20> Desired Color: [ ][ ][ ][ ] <20> *
* <20> <20> *
* <20> Opponent: Name <20> *
* <20> Scenario: Description <20> *
* <20> Credits: xxxx <20> *
* <20> Bases: ON <20> *
* <20> Crates: ON <20> *
* <20> Tiberium: ON <20> *
* <20> Ghosts: ON <20> *
* <20> <20> *
* <20> [Cancel] <20> *
* <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ <20> *
* <20> <20> <20> <20> *
* <20> <20> <20> <20> *
* <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> *
* <20> [Send Message] <20> *
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* true = success, false = cancel *
* *
* WARNINGS: *
* MPlayerName & MPlayerGameName must contain this player's name. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
int Com_Show_Scenario_Dialog(void)
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 306*factor; // dialog width
int d_dialog_h = 187*factor; // dialog height
int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
int d_dialog_y = ((200*factor - d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 6*factor+1; // ht of 6-pt text
int d_margin1 = 5*factor; // margin width/height
int d_margin2 = 2*factor; // margin width/height
int d_name_w = 70*factor;
int d_name_h = 9*factor;
int d_name_x = d_dialog_cx;
int d_name_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h;
int d_gdi_w = 30*factor;
int d_gdi_h = 9*factor;
int d_gdi_x = d_dialog_cx;
int d_gdi_y = d_name_y + d_name_h + d_margin2;
int d_nod_w = 30*factor;
int d_nod_h = 9*factor;
int d_nod_x = d_gdi_x + d_gdi_w + d_margin2;
int d_nod_y = d_gdi_y;
int d_color_w = 10*factor;
int d_color_h = 9*factor;
int d_color_y = d_gdi_y + d_gdi_h + d_margin2;
int d_opponent_y = d_color_y + d_color_h + d_margin1;
int d_scenario_y = d_opponent_y + d_txt6_h;
int d_credits_y = d_scenario_y + d_txt6_h;
int d_count_y = d_credits_y + d_txt6_h;
int d_level_y = d_count_y + d_txt6_h;
int d_bases_y = d_level_y + d_txt6_h;
int d_goodies_y = d_bases_y + d_txt6_h;
int d_tiberium_y = d_goodies_y + d_txt6_h;
int d_ghosts_y = d_tiberium_y + d_txt6_h;
int d_cancel_w = 45*factor;
int d_cancel_h = 9*factor;
int d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
int d_cancel_y = d_ghosts_y + d_txt6_h + d_margin1;
int d_message_w = d_dialog_w - (d_margin1 * 2);
int d_message_h = 34*factor;
int d_message_x = d_dialog_x + d_margin1;
int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
int d_send_w = 80*factor;
int d_send_h = 9*factor;
int d_send_x = d_dialog_cx - (d_send_w / 2);
int d_send_y = d_message_y + d_message_h + d_margin2;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_NAME = 100,
BUTTON_GDI,
BUTTON_NOD,
BUTTON_CANCEL,
BUTTON_SEND,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_MESSAGE,
REDRAW_COLORS,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
BOOL process = true; // process while true
KeyNumType input;
char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
int transmit; // 1 = re-transmit new game options
int first; // 1 = no packets received yet
int cbox_x[] = { d_dialog_cx,
d_dialog_cx + d_color_w,
d_dialog_cx + (d_color_w * 2),
d_dialog_cx + (d_color_w * 3),
d_dialog_cx + (d_color_w * 4),
d_dialog_cx + (d_color_w * 5)};
int parms_received = 0; // 1 = game options received
int changed = 0; // 1 = user has changed an option
int rc;
int recsignedoff = 0;
int i;
int version;
char txt[80];
unsigned long starttime;
unsigned long timingtime;
unsigned long lastmsgtime;
unsigned long lastredrawtime;
unsigned long transmittime = 0;
int packetlen;
bool oppscorescreen = false;
bool gameoptions = false;
EventClass *event; // event ptr
unsigned long msg_timeout = 1200; // init to 20 seconds
int message_length;
int sent_so_far;
unsigned short magic_number;
unsigned short crc;
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
EditClass name_edt (BUTTON_NAME,
namebuf, MPLAYER_NAME_MAX,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
TextButtonClass gdibtn(BUTTON_GDI, TXT_G_D_I,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);
TextButtonClass nodbtn(BUTTON_NOD, TXT_N_O_D,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_nod_x, d_nod_y, d_nod_w, d_nod_h);
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_cancel_x, d_cancel_y);
#else
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
#endif
TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_send_x, d_send_y);
#else
d_send_x, d_send_y, d_send_w, d_send_h);
#endif
/*
------------------------- Build the button list --------------------------
*/
commands = &name_edt;
gdibtn.Add_Tail(*commands);
nodbtn.Add_Tail(*commands);
cancelbtn.Add_Tail(*commands);
sendbtn.Add_Tail(*commands);
/*
----------------------------- Various Inits ------------------------------
*/
/*........................................................................
Init player name & house
........................................................................*/
MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
strcpy (namebuf, MPlayerName); // set my name
name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
name_edt.Set_Color(MPlayerTColors[MPlayerColorIdx]);
if (MPlayerHouse==HOUSE_GOOD) {
gdibtn.Turn_On();
} else {
nodbtn.Turn_On();
}
Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
transmit = 1;
first = 1;
/*........................................................................
Init the message display system
........................................................................*/
Messages.Init (d_message_x + 2*factor, d_message_y + 2*factor, 4, MAX_MESSAGE_LENGTH, d_txt6_h);
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
extern char ModemRXString[];
if (strlen(ModemRXString) > 36)
ModemRXString[36] = 0;
if (strlen(ModemRXString) > 0)
Messages.Add_Message (ModemRXString, CC_TAN,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, 0, 0);
ModemRXString[0] = '\0';
/*
---------------------------- Init Mono Output ----------------------------
*/
#if(SHOW_MONO)
NullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType),
SerialPacketNames, 106);
NullModem.Mono_Debug_Print(1);
#endif
/*
---------------------------- Processing loop -----------------------------
*/
NullModem.Reset_Response_Time(); // clear response time
timingtime = lastmsgtime = lastredrawtime = TickCount.Time();
while (Get_Mouse_State() > 0) Show_Mouse();
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
if (display >= REDRAW_BACKGROUND) {
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
/*...............................................................
Dialog & Field labels
...............................................................*/
#ifdef FORCE_WINSOCK
if (Winsock.Get_Connected()){
Draw_Caption (TXT_JOIN_INTERNET_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}else{
Draw_Caption (TXT_JOIN_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}
#else
Draw_Caption (TXT_JOIN_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
#endif //FORCE_WINSOCK
Fancy_Text_Print(TXT_YOUR_NAME,
d_name_x - 5*factor, d_name_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print(TXT_SIDE_COLON,
d_gdi_x - 5*factor, d_gdi_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print(TXT_COLOR_COLON,
cbox_x[0] - 5*factor, d_color_y + 1*factor,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
/*..................................................................
Draw the color boxes
..................................................................*/
if (display >= REDRAW_COLORS) {
for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
LogicPage->Fill_Rect (cbox_x[i] + 1*factor, d_color_y + 1*factor,
cbox_x[i] + 1*factor + d_color_w - 2*factor, d_color_y + 1*factor + d_color_h - 2*factor,
MPlayerGColors[i]);
if (i == MPlayerColorIdx) {
Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
BOXSTYLE_GREEN_DOWN, false);
} else {
Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
BOXSTYLE_GREEN_RAISED, false);
}
}
}
/*..................................................................
Draw the message:
- Erase an old message first
..................................................................*/
if (display >= REDRAW_MESSAGE) {
Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
BOXSTYLE_GREEN_BORDER, true);
Messages.Draw();
LogicPage->Fill_Rect( d_dialog_x + 2*factor,
d_opponent_y,
d_dialog_x + d_dialog_w - 4*factor,
d_ghosts_y + d_txt6_h,
BLACK);
if (parms_received) {
if (oppscorescreen) {
sprintf(txt,"%s",Text_String(TXT_WAITING_FOR_OPPONENT));
int txtwidth = String_Pixel_Width( txt );
Fancy_Text_Print (txt, d_dialog_cx - (txtwidth / 2),
d_opponent_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
} else {
/*............................................................
Opponent's name
............................................................*/
Fancy_Text_Print (TXT_OPPONENT_COLON, d_dialog_cx - 3*factor,
d_opponent_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (TheirHouse == HOUSE_GOOD) {
sprintf(txt,"%s %s",TheirName,Text_String(TXT_G_D_I));
} else {
sprintf(txt,"%s %s",TheirName,Text_String(TXT_N_O_D));
}
Fancy_Text_Print (txt, d_dialog_cx,
d_opponent_y, MPlayerTColors[TheirColor], TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Scenario description
............................................................*/
Fancy_Text_Print (TXT_SCENARIO_COLON, d_dialog_cx - 3*factor,
d_scenario_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (ScenarioIdx != -1) {
sprintf(txt,"%s", MPlayerScenarios[ScenarioIdx]);
Fancy_Text_Print (txt, d_dialog_cx,
d_scenario_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
} else {
strcpy(txt,Text_String(TXT_NOT_FOUND));
Fancy_Text_Print (txt, d_dialog_cx,
d_scenario_y, RED, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
/*............................................................
Credits
............................................................*/
Fancy_Text_Print (TXT_START_CREDITS_COLON, d_dialog_cx - 3*factor,
d_credits_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
sprintf(txt,"%d",MPlayerCredits);
Fancy_Text_Print (txt, d_dialog_cx,
d_credits_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Count
............................................................*/
Fancy_Text_Print (TXT_COUNT, d_dialog_cx - 3*factor,
d_count_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
sprintf( txt, "%d ", MPlayerUnitCount );
Fancy_Text_Print (txt, d_dialog_cx,
d_count_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Level
............................................................*/
Fancy_Text_Print (TXT_LEVEL, d_dialog_cx - 3*factor,
d_level_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
sprintf(txt, "%d ", BuildLevel);
} else {
sprintf(txt, "**");
}
Fancy_Text_Print (txt, d_dialog_cx,
d_level_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Bases status
............................................................*/
Fancy_Text_Print (TXT_BASES_COLON, d_dialog_cx - 3*factor,
d_bases_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (MPlayerBases) {
strcpy(txt,Text_String(TXT_ON));
} else {
strcpy(txt,Text_String(TXT_OFF));
}
Fancy_Text_Print (txt, d_dialog_cx,
d_bases_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Tiberium status
............................................................*/
Fancy_Text_Print (TXT_TIBERIUM_COLON, d_dialog_cx - 3*factor,
d_tiberium_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (MPlayerTiberium) {
strcpy(txt,Text_String(TXT_ON));
} else {
strcpy(txt,Text_String(TXT_OFF));
}
Fancy_Text_Print (txt, d_dialog_cx,
d_tiberium_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Goodies status
............................................................*/
Fancy_Text_Print (TXT_CRATES_COLON, d_dialog_cx - 3*factor,
d_goodies_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (MPlayerGoodies) {
strcpy(txt,Text_String(TXT_ON));
} else {
strcpy(txt,Text_String(TXT_OFF));
}
Fancy_Text_Print (txt, d_dialog_cx,
d_goodies_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*............................................................
Capture the flag or AI player ON/OFF
............................................................*/
if ( Special.IsCaptureTheFlag ) {
strcpy( txt, Text_String( TXT_CAPTURE_THE_FLAG ) );
strcat( txt, ":" );
Fancy_Text_Print (txt, d_dialog_cx - 3*factor,
d_ghosts_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
strcpy(txt,Text_String(TXT_ON));
Fancy_Text_Print (txt, d_dialog_cx,
d_ghosts_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
} else {
/*............................................................
Ghost player status
............................................................*/
Fancy_Text_Print (TXT_AI_PLAYERS_COLON, d_dialog_cx - 3*factor,
d_ghosts_y, CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
if (MPlayerGhosts) {
strcpy(txt,Text_String(TXT_ON));
} else {
strcpy(txt,Text_String(TXT_OFF));
}
Fancy_Text_Print (txt, d_dialog_cx,
d_ghosts_y, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
}
}
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
commands->Flag_List_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
---------------------------- Process input ----------------------------
*/
switch (input) {
/*------------------------------------------------------------------
User clicks on a color button
------------------------------------------------------------------*/
case KN_LMOUSE:
if (_Kbd->MouseQX > cbox_x[0] &&
_Kbd->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
_Kbd->MouseQY > d_color_y &&
_Kbd->MouseQY < (d_color_y + d_color_h)) {
/*.........................................................
Compute my preferred color as the one I clicked on.
.........................................................*/
MPlayerPrefColor = (_Kbd->MouseQX - cbox_x[0]) / d_color_w;
changed = 1;
/*.........................................................
If 'TheirColor' is set to the other player's color, make
sure we can't pick that color.
.........................................................*/
if (parms_received) {
if (MPlayerPrefColor == TheirColor)
break;
}
MPlayerColorIdx = MPlayerPrefColor;
name_edt.Set_Color(MPlayerTColors[MPlayerColorIdx]);
name_edt.Flag_To_Redraw();
display = REDRAW_COLORS;
strcpy (MPlayerName, namebuf);
transmit = 1;
}
break;
/*------------------------------------------------------------------
House Buttons: set the player's desired House
------------------------------------------------------------------*/
case (BUTTON_GDI | KN_BUTTON):
MPlayerHouse = HOUSE_GOOD;
gdibtn.Turn_On();
nodbtn.Turn_Off();
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
case (BUTTON_NOD | KN_BUTTON):
MPlayerHouse = HOUSE_BAD;
gdibtn.Turn_Off();
nodbtn.Turn_On();
strcpy (MPlayerName, namebuf);
transmit = 1;
break;
/*------------------------------------------------------------------
User edits the name value; retransmit
------------------------------------------------------------------*/
case (BUTTON_NAME | KN_BUTTON):
strcpy (MPlayerName, namebuf);
transmit = 1;
changed = 1;
break;
/*------------------------------------------------------------------
CANCEL: send a SIGN_OFF, bail out with error code
------------------------------------------------------------------*/
case (KN_ESC):
if (Messages.Get_Edit_Buf() != NULL) {
Messages.Input(input);
display = REDRAW_MESSAGE;
break;
}
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
/*------------------------------------------------------------------
Default: manage the inter-player messages
------------------------------------------------------------------*/
default:
/*...............................................................
F4/SEND/'M' = send a message
...............................................................*/
if (Messages.Get_Edit_Buf()==NULL) {
if (input == KN_M || input==(BUTTON_SEND | KN_BUTTON) ||
input == KN_F4) {
memset (txt, 0, 80);
strcpy(txt,Text_String(TXT_MESSAGE)); // "Message:"
Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
display = REDRAW_MESSAGE;
name_edt.Clear_Focus();
name_edt.Flag_To_Redraw();
break;
}
} else {
if ( input == (BUTTON_SEND | KN_BUTTON) ) {
input = KN_RETURN;
}
}
/*...............................................................
Manage the message system (get rid of old messages)
...............................................................*/
if (Messages.Manage()) {
display = REDRAW_MESSAGE;
}
/*...............................................................
Re-draw the messages & service keyboard input for any message
being edited.
...............................................................*/
i = Messages.Input(input);
/*...............................................................
If 'Input' returned 1, it means refresh the message display.
...............................................................*/
if (i==1) {
Messages.Draw();
} else {
/*...............................................................
If 'Input' returned 2, it means redraw the message display.
...............................................................*/
if (i==2) {
display = REDRAW_MESSAGE;
} else {
/*...............................................................
If 'input' returned 3, it means send the current message.
...............................................................*/
if (i==3) {
sent_so_far = 0;
magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
message_length = strlen(Messages.Get_Edit_Buf());
crc = (unsigned short)
(Calculate_CRC(Messages.Get_Edit_Buf(), message_length) &0xffff);
while (sent_so_far < message_length){
SendPacket.Command = SERIAL_MESSAGE;
strcpy (SendPacket.Name, MPlayerName);
SendPacket.ID = Build_MPlayerID(MPlayerColorIdx, MPlayerHouse);
memcpy (SendPacket.Message, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
*(SendPacket.Message + COMPAT_MESSAGE_LENGTH-5) = 0;
*((unsigned short*)(SendPacket.Message + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
*((unsigned short*)(SendPacket.Message + COMPAT_MESSAGE_LENGTH-2)) = crc;
/*..................................................................
Send the message
..................................................................*/
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
NullModem.Service();
/*..................................................................
Add the message to our own screen
..................................................................*/
sprintf(txt, Text_String (TXT_FROM), MPlayerName, SendPacket.Message);
Messages.Add_Message (txt, MPlayerTColors[MPlayerColorIdx],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
magic_number++;
sent_so_far += COMPAT_MESSAGE_LENGTH-5;
}
display = REDRAW_MESSAGE;
}
}
}
break;
}
/*---------------------------------------------------------------------
Detect editing of the name buffer, transmit new values to players
---------------------------------------------------------------------*/
if (strcmp (namebuf, MPlayerName)) {
strcpy (MPlayerName, namebuf);
transmit = 1;
changed = 1;
}
/*---------------------------------------------------------------------
If our Transmit flag is set, we need to send out a game option packet
---------------------------------------------------------------------*/
if (transmit && (TickCount.Time() - transmittime) > PACKET_RETRANS_TIME) {
SendPacket.Command = SERIAL_GAME_OPTIONS;
strcpy (SendPacket.Name, MPlayerName);
#ifdef PATCH
if (IsV107) {
SendPacket.Version = 1;
} else {
SendPacket.Version = 2;
}
#else
SendPacket.Version = Version_Number();
#endif
SendPacket.House = MPlayerHouse;
SendPacket.Color = MPlayerColorIdx;
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
transmittime = TickCount.Time();
transmit = 0;
}
//
// send a timing packet if enough time has gone by.
//
if ( (TickCount.Time() - timingtime) > PACKET_TIMING_TIMEOUT) {
SendPacket.Command = SERIAL_TIMING;
SendPacket.ResponseTime = NullModem.Response_Time();
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);
timingtime = TickCount.Time();
}
/*---------------------------------------------------------------------
Check for an incoming message
---------------------------------------------------------------------*/
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
// Smart_Printf( "received packet of length %d\n", packetlen );
lastmsgtime = TickCount.Time();
msg_timeout = 600;
// are we getting our own packets back??
if (ReceivePacket.Command >= SERIAL_CONNECT &&
ReceivePacket.Command < SERIAL_LAST_COMMAND &&
ReceivePacket.Command != SERIAL_MESSAGE &&
ReceivePacket.ID == ModemGameToPlay) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
break;
}
event = (EventClass *)&ReceivePacket;
if (event->Type <= EventClass::FRAMEINFO) {
if ( (TickCount.Time() - lastredrawtime) > PACKET_REDRAW_TIME) {
lastredrawtime = TickCount.Time();
oppscorescreen = true;
display = REDRAW_MESSAGE;
parms_received = 1;
}
} else {
switch ( ReceivePacket.Command ) {
/*..................................................................
Other system signs off: Give it time to receive my ACK, then show
a message.
..................................................................*/
case (SERIAL_SIGN_OFF):
starttime = TickCount.Time();
while ( (TickCount.Time() - starttime) < 60)
NullModem.Service();
CCMessageBox().Process(TXT_USER_SIGNED_OFF);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
recsignedoff = true;
break;
/*..................................................................
Game Options: Store all options; check my color & game version.
..................................................................*/
case (SERIAL_GAME_OPTIONS):
oppscorescreen = false;
gameoptions = true;
display = REDRAW_MESSAGE;
parms_received = 1;
strcpy (TheirName, ReceivePacket.Name);
TheirColor = ReceivePacket.Color;
TheirHouse = ReceivePacket.House;
/*...............................................................
Make sure I don't have the same color as the other guy.
...............................................................*/
if (MPlayerColorIdx == TheirColor) {
// force transmitting of game options packet
transmit = 1;
transmittime = 0;
MPlayerColorIdx = TheirColor + 1;
if (MPlayerColorIdx >= 6)
MPlayerColorIdx = 0;
name_edt.Set_Color(MPlayerTColors[MPlayerColorIdx]);
name_edt.Flag_To_Redraw();
display = REDRAW_COLORS;
}
/*...............................................................
Save scenario settings.
...............................................................*/
MPlayerCredits = ReceivePacket.Credits;
MPlayerBases = ReceivePacket.IsBases;
MPlayerTiberium = ReceivePacket.IsTiberium;
MPlayerGoodies = ReceivePacket.IsGoodies;
MPlayerGhosts = ReceivePacket.IsGhosties;
BuildLevel = ReceivePacket.BuildLevel;
MPlayerUnitCount = ReceivePacket.UnitCount;
Seed = ReceivePacket.Seed;
Special = ReceivePacket.Special;
Options.GameSpeed = ReceivePacket.GameSpeed;
if (MPlayerTiberium) {
Special.IsTGrowth = 1;
Special.IsTSpread = 1;
} else {
Special.IsTGrowth = 0;
Special.IsTSpread = 0;
}
/*...............................................................
Find the index of the scenario number; if it's not found, leave
it at -1.
...............................................................*/
ScenarioIdx = -1;
for (i = 0; i < MPlayerFilenum.Count(); i++) {
if (ReceivePacket.Scenario == MPlayerFilenum[i])
ScenarioIdx = i;
}
/*...............................................................
Check our version numbers; if they're incompatible, sign off.
...............................................................*/
#ifdef PATCH
if (IsV107) {
version = 1;
} else {
version = 2;
}
#else
version = Version_Number();
#endif
if (ReceivePacket.Version > version) {
CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
} else {
if (ReceivePacket.Version < version) {
CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
}
}
/*...............................................................
If this is the first game-options packet we've received, transmit
our options to him.
...............................................................*/
if (first) {
first = 0;
// force transmitting of game options packet
transmit = 1;
transmittime = 0;
}
break;
/*..................................................................
GO: Exit this routine with a success code.
..................................................................*/
case (SERIAL_GO):
//
// calculated one way delay for a packet and overall delay
// to execute a packet
//
MPlayerMaxAhead = MAX( (ReceivePacket.ResponseTime / 8), 2);
process = false;
rc = true;
break;
/*..................................................................
Incoming message: add to our list
..................................................................*/
case (SERIAL_MESSAGE):
oppscorescreen = false;
sprintf(txt, Text_String (TXT_FROM), ReceivePacket.Name,
ReceivePacket.Message);
magic_number = *((unsigned short*)(ReceivePacket.Message + COMPAT_MESSAGE_LENGTH-4));
crc = *((unsigned short*)(ReceivePacket.Message + COMPAT_MESSAGE_LENGTH-2));
Messages.Add_Message (txt, MPlayerTColors[MPlayerID_To_ColorIndex(ReceivePacket.ID)],
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
display = REDRAW_MESSAGE;
break;
//
// throw away timing packet
//
case (SERIAL_TIMING):
oppscorescreen = false;
break;
//
// print msg waiting for opponent
//
case (SERIAL_SCORE_SCREEN):
// Smart_Printf( "received score screen\n" );
oppscorescreen = true;
display = REDRAW_MESSAGE;
parms_received = 1;
break;
default:
break;
}
}
}
// if we haven't received a msg for 10 seconds exit
//if ( ((TickCount.Time() - lastmsgtime) > msg_timeout) ||
//(Winsock.Get_Connected() && Winsock.Get_Connection_Status == TcpipManagerClass::CONNECTION_LOST)) {
if ( (TickCount.Time() - lastmsgtime) > msg_timeout) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
}
/*---------------------------------------------------------------------
Service the connection
---------------------------------------------------------------------*/
NullModem.Service();
} /* end of while */
/*------------------------------------------------------------------------
Sort player ID's, so we can execute commands in the same order on both
machines.
------------------------------------------------------------------------*/
if (rc) {
/*.....................................................................
Set the number of players in this game, and my ID
.....................................................................*/
MPlayerCount = 2;
MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
TheirID = Build_MPlayerID (TheirColor,TheirHouse);
/*.....................................................................
Store every player's ID in the MPlayerID[] array. This array will
determine the order of event execution, so the ID's must be stored
in the same order on all systems.
.....................................................................*/
if (TheirID < MPlayerLocalID) {
MPlayerID[0] = TheirID;
MPlayerID[1] = MPlayerLocalID;
strcpy (MPlayerNames[0], TheirName);
strcpy (MPlayerNames[1], MPlayerName);
} else {
MPlayerID[0] = MPlayerLocalID;
MPlayerID[1] = TheirID;
strcpy (MPlayerNames[0], MPlayerName);
strcpy (MPlayerNames[1], TheirName);
}
/*.....................................................................
Get the scenario filename
.....................................................................*/
Scenario = MPlayerFilenum[ScenarioIdx];
starttime = TickCount.Time();
while ( ( NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_SENDING_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
NullModem.Service();
Keyboard::Check(); //Make sure the message loop gets called
}
// clear queue to keep from doing any resends
NullModem.Init_Send_Queue();
} else {
if ( !recsignedoff ) {
/*.....................................................................
Broadcast my sign-off over my network
.....................................................................*/
SendPacket.Command = SERIAL_SIGN_OFF;
SendPacket.Color = MPlayerLocalID; // use Color for ID
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( (NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_CANCEL_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {
// are we getting our own packets back??
if (ReceivePacket.Command == SERIAL_SIGN_OFF
&& ReceivePacket.ID == ModemGameToPlay) {
// exit while
break;
}
}
NullModem.Service();
}
}
Shutdown_Modem();
}
/*------------------------------------------------------------------------
Restore screen
------------------------------------------------------------------------*/
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Show_Mouse();
/*------------------------------------------------------------------------
Save any changes made to our options
------------------------------------------------------------------------*/
if (changed) {
Write_MultiPlayer_Settings ();
}
return(rc);
} /* end of Com_Show_Scenario_Dialog */
/***************************************************************************
* Phone_Dialog -- Lets user edit phone directory & dial *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* true = dial the current phone book entry, false = cancel. *
* *
* WARNINGS: *
* Serial options must have been read from CC.INI. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
static int Phone_Dialog (void)
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 280 *factor; // dialog width
int d_dialog_h = 150 *factor; // dialog height
int d_dialog_x = ((320 *factor - d_dialog_w) / 2); // dialog x-coord
int d_dialog_y = ((200 *factor- d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 11 *factor; // ht of 6-pt text
int d_margin = 7 *factor; // margin width/height
int d_phonelist_w = 268 *factor;
int d_phonelist_h = 87 *factor;
int d_phonelist_x = d_dialog_cx - (d_phonelist_w / 2);
int d_phonelist_y = d_dialog_y + d_margin + d_txt6_h + 11*factor;
int d_add_w = 45*factor;
int d_add_h = 9*factor;
int d_add_x = d_dialog_cx - (d_add_w / 2) - d_margin - d_add_w;
int d_add_y = d_phonelist_y + d_phonelist_h + d_margin;
int d_edit_w = 45*factor;
int d_edit_h = 9*factor;
int d_edit_x = d_dialog_cx - (d_edit_w / 2);
int d_edit_y = d_phonelist_y + d_phonelist_h + d_margin;
int d_delete_w = 45*factor;
int d_delete_h = 9*factor;
int d_delete_x = d_dialog_cx + (d_delete_w / 2) + d_margin;
int d_delete_y = d_phonelist_y + d_phonelist_h + d_margin;
int d_numedit_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6*factor) + 3*factor;
int d_numedit_h = 9*factor;
int d_numedit_x = d_dialog_cx - (d_numedit_w / 2);
int d_numedit_y = d_add_y + d_add_h + d_margin;
int d_dial_w = 45*factor;
int d_dial_h = 9*factor;
int d_dial_x = d_dialog_cx - (d_numedit_w / 2) - d_margin - d_dial_w;
int d_dial_y = d_add_y + d_add_h + d_margin;
int d_cancel_w = 45*factor;
int d_cancel_h = 9*factor;
int d_cancel_x = d_dialog_cx + (d_numedit_w / 2) + d_margin;
int d_cancel_y = d_add_y + d_add_h + d_margin;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_PHONELIST = 100,
BUTTON_ADD,
BUTTON_EDIT,
BUTTON_DELETE,
BUTTON_DIAL,
BUTTON_CANCEL,
BUTTON_NUMEDIT,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
BOOL process = true; // process while true
KeyNumType input;
char phone_num[ PhoneEntryClass::PHONE_MAX_NUM ] = { 0 }; // buffer for editing phone #
int rc;
int i;
int tabs[] = {123*factor, 207*factor}; // tabs for list box
char *item; // for removing items from list box
PhoneEntryClass *p_entry; // for creating / editing phonebook entries
int changed = 0; // 1 = save changes to INI file
int firsttime = 0;
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
void const *up_button;
void const *down_button;
if (InMainLoop){
up_button = Hires_Retrieve("BTN-UP.SHP");
down_button = Hires_Retrieve("BTN-DN.SHP");
}else{
up_button = Hires_Retrieve("BTN-UP2.SHP");
down_button = Hires_Retrieve("BTN-DN2.SHP");
}
ListClass phonelist(BUTTON_PHONELIST,
d_phonelist_x, d_phonelist_y, d_phonelist_w, d_phonelist_h,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
up_button,
down_button);
TextButtonClass addbtn(BUTTON_ADD, TXT_ADD,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#ifdef FRENCH
d_add_x-4, d_add_y);
#else
d_add_x, d_add_y, d_add_w, d_add_h);
#endif
TextButtonClass editbtn(BUTTON_EDIT, TXT_EDIT,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_edit_x, d_edit_y, d_edit_w, d_edit_h);
TextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#ifdef FRENCH
d_delete_x, d_delete_y);
#else
d_delete_x, d_delete_y, d_delete_w, d_delete_h);
#endif
TextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
/* ###Change collision detected! C:\PROJECTS\CODE\NULLDLG.CPP... */
d_dial_x, d_dial_y, d_dial_w, d_dial_h);
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
#if (GERMAN | FRENCH)
d_cancel_x, d_cancel_y);
#else
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
#endif
EditClass numedit (BUTTON_NUMEDIT,
phone_num, PhoneEntryClass::PHONE_MAX_NUM,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_numedit_x, d_numedit_y, d_numedit_w, d_numedit_h, EditClass::ALPHANUMERIC);
/*
------------------------- Build the button list --------------------------
*/
commands = &phonelist;
addbtn.Add_Tail(*commands);
editbtn.Add_Tail(*commands);
deletebtn.Add_Tail(*commands);
dialbtn.Add_Tail(*commands);
cancelbtn.Add_Tail(*commands);
numedit.Add_Tail(*commands);
dialbtn.Turn_On();
/*
----------------------------- Various Inits ------------------------------
*/
/*........................................................................
Fill in the phone directory list box
........................................................................*/
phonelist.Set_Tabs(tabs);
Build_Phone_Listbox(&phonelist, &numedit, phone_num);
if (CurPhoneIdx == -1) {
firsttime = 1;
}
/*
---------------------------- Processing loop -----------------------------
*/
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
if (display >= REDRAW_BACKGROUND) {
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
// init font variables
Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*...............................................................
Dialog & Field labels
...............................................................*/
Draw_Caption (TXT_PHONE_LIST, d_dialog_x, d_dialog_y, d_dialog_w);
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
phonelist.Flag_To_Redraw();
addbtn.Flag_To_Redraw();
editbtn.Flag_To_Redraw();
deletebtn.Flag_To_Redraw();
dialbtn.Flag_To_Redraw();
cancelbtn.Flag_To_Redraw();
numedit.Flag_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
if ( firsttime ) {
numedit.Set_Focus();
numedit.Flag_To_Redraw();
input = commands->Input();
firsttime = 0;
}
/*
---------------------------- Process input ----------------------------
*/
switch (input) {
/*------------------------------------------------------------------
New phone listing selected.
------------------------------------------------------------------*/
case (BUTTON_PHONELIST | KN_BUTTON):
/*...............................................................
Detect a change in the selected item; update CurPhoneIdx, and
the edit box buffer.
...............................................................*/
if (phonelist.Current_Index() != CurPhoneIdx) {
CurPhoneIdx = phonelist.Current_Index();
strcpy (phone_num, PhoneBook[CurPhoneIdx]->Number);
numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );
changed = 1;
}
break;
/*------------------------------------------------------------------
Add a new entry
------------------------------------------------------------------*/
case (BUTTON_ADD | KN_BUTTON):
/*...............................................................
Allocate a new phone book entry
...............................................................*/
p_entry = new PhoneEntryClass();
p_entry->Name[0] = 0;
p_entry->Number[0] = 0;
p_entry->Settings.Port = 0;
p_entry->Settings.IRQ = -1;
p_entry->Settings.Baud = -1;
p_entry->Settings.DialMethod = DIAL_TOUCH_TONE;
p_entry->Settings.InitStringIndex = 0;
p_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;
p_entry->Settings.CallWaitString[0] = 0;
/*...............................................................
Invoke the entry editor; if user clicks Save, add the new entry
to the list, and rebuild the list box.
...............................................................*/
if ( Edit_Phone_Dialog( p_entry ) ) {
PhoneBook.Add (p_entry);
Build_Phone_Listbox( &phonelist, &numedit, phone_num );
/*............................................................
Set the current listbox index to the newly-added item.
............................................................*/
for (i = 0; i < PhoneBook.Count(); i++) {
if (p_entry == PhoneBook[i]) {
CurPhoneIdx = i;
strcpy (phone_num, PhoneBook[CurPhoneIdx]->Number);
numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );
phonelist.Set_Selected_Index( CurPhoneIdx );
}
}
changed = 1;
} else {
/*...............................................................
If the user clicked Cancel, delete the entry & keep looping.
...............................................................*/
delete p_entry;
}
display = REDRAW_ALL;
break;
/*------------------------------------------------------------------
Edit the current entry
------------------------------------------------------------------*/
case (BUTTON_EDIT | KN_BUTTON):
/*...............................................................
Do nothing if no entry is selected.
...............................................................*/
if (CurPhoneIdx==-1)
break;
/*...............................................................
Allocate a new entry & copy the currently-selected entry into it
...............................................................*/
p_entry = new PhoneEntryClass();
(*p_entry) = (*PhoneBook[CurPhoneIdx]);
/*...............................................................
Pass the new entry to the entry editor; if the user selects OK,
copy the data back into our phone book. Rebuild the list so
the changes show up in the list box.
...............................................................*/
if ( Edit_Phone_Dialog( p_entry ) ) {
(*PhoneBook[CurPhoneIdx]) = (*p_entry);
Build_Phone_Listbox(&phonelist, &numedit, phone_num);
/*............................................................
Set the current listbox index to the newly-added item.
............................................................*/
for (i = 0; i < PhoneBook.Count(); i++) {
if (PhoneBook[CurPhoneIdx] == PhoneBook[i]) {
CurPhoneIdx = i;
strcpy (phone_num, PhoneBook[CurPhoneIdx]->Number);
numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );
phonelist.Set_Selected_Index( CurPhoneIdx );
}
}
changed = 1;
}
delete p_entry;
display = REDRAW_ALL;
break;
/*------------------------------------------------------------------
Delete the current entry
------------------------------------------------------------------*/
case (BUTTON_DELETE | KN_BUTTON):
/*...............................................................
Do nothing if no entry is selected.
...............................................................*/
if (CurPhoneIdx == -1)
break;
/*...............................................................
Delete the current item & rebuild the phone listbox
...............................................................*/
PhoneBook.Delete (CurPhoneIdx);
Build_Phone_Listbox(&phonelist, &numedit, phone_num);
if (CurPhoneIdx == -1) {
*phone_num = 0;
numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM );
}
changed = 1;
break;
/*------------------------------------------------------------------
Dial the current number
------------------------------------------------------------------*/
case (KN_RETURN):
dialbtn.IsPressed = true;
dialbtn.Draw_Me(true);
// fall thru
case (BUTTON_DIAL | KN_BUTTON):
/*...............................................................
If no item is selected, just dial the number in the phone #
edit box:
- Create a new phone entry
- Copy the phone number into it
- Set settings to defaults
...............................................................*/
if (CurPhoneIdx == -1 ||
strcmp( PhoneBook[CurPhoneIdx]->Number, phone_num) ) {
if ( strlen(phone_num) == 0) { // do not dial
dialbtn.IsPressed = false;
dialbtn.Flag_To_Redraw();
break;
}
p_entry = new PhoneEntryClass();
strcpy( p_entry->Name, "NONAME" );
strcpy( p_entry->Number, phone_num);
p_entry->Settings.Port = 0;
p_entry->Settings.IRQ = -1;
p_entry->Settings.Baud = -1;
p_entry->Settings.DialMethod = DIAL_TOUCH_TONE;
p_entry->Settings.InitStringIndex = 0;
p_entry->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;
p_entry->Settings.CallWaitString[0] = 0;
PhoneBook.Add (p_entry);
Build_Phone_Listbox(&phonelist, &numedit, phone_num);
/*............................................................
Set the current listbox index to the newly-added item.
............................................................*/
for (i = 0; i < PhoneBook.Count(); i++) {
if (p_entry == PhoneBook[i]) {
CurPhoneIdx = i;
}
}
changed = 1;
}
process = false;
rc = true;
break;
/*------------------------------------------------------------------
CANCEL: bail out
------------------------------------------------------------------*/
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
}
} /* end of while */
/*------------------------------------------------------------------------
Save any changes we've made to the phone list or settings
------------------------------------------------------------------------*/
if (changed) {
Write_MultiPlayer_Settings ();
}
/*------------------------------------------------------------------------
Clear the list box
------------------------------------------------------------------------*/
while (phonelist.Count()) {
item = (char *)phonelist.Get_Item(0);
phonelist.Remove_Item(item);
delete [] item;
}
return(rc);
} /* end of Phone_Dialog */
/***************************************************************************
* Build_Phone_Listbox -- [re]builds the phone entry listbox *
* *
* This routine rebuilds the phone list box from scratch; it also updates *
* the contents of the phone # edit field. *
* *
* INPUT: *
* list ptr to list box *
* edit ptr to edit box *
* buf ptr to buffer for phone # *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
static void Build_Phone_Listbox (ListClass *list, EditClass *edit, char *buf)
{
int i;
char *item;
char phonename[21];
char phonenum[15];
/*........................................................................
Clear the list
........................................................................*/
while (list->Count()) {
item = (char *)(list->Get_Item(0));
list->Remove_Item(item);
delete [] item;
}
/*
** Now sort the phone list by name then number
*/
qsort ((void *)(&PhoneBook[0]), PhoneBook.Count(), sizeof(class PhoneEntryClass *), Phone_Compare);
/*........................................................................
Build the list
........................................................................*/
for (i = 0; i < PhoneBook.Count(); i++) {
item = new char[80];
if ( !(strlen( PhoneBook[i]->Name )) ) {
strcpy( phonename, " " );
} else {
strncpy( phonename, PhoneBook[i]->Name, 20 );
phonename[21] = 0;
}
if ( !(strlen( PhoneBook[i]->Number )) ) {
strcpy( phonenum, " " );
} else {
if ( strlen( PhoneBook[i]->Number ) < 14) {
strcpy( phonenum, PhoneBook[i]->Number );
} else {
strncpy( phonenum, PhoneBook[i]->Number, 12 );
phonenum[12] = 0;
strcat( phonenum, "..." );
}
}
if (PhoneBook[i]->Settings.Baud != -1) {
sprintf(item,"%s\t%s\t%d", phonename, phonenum,
PhoneBook[i]->Settings.Baud);
} else {
sprintf(item,"%s\t%s\t[%s]", phonename, phonenum,
Text_String(TXT_DEFAULT));
}
list->Add_Item(item);
}
list->Flag_To_Redraw();
/*........................................................................
Init the current phone book index
........................................................................*/
if (list->Count() == 0 || CurPhoneIdx < -1) {
CurPhoneIdx = -1;
} else {
if (CurPhoneIdx >= list->Count() ) {
CurPhoneIdx = 0;
}
}
/*........................................................................
Fill in phone number edit buffer
........................................................................*/
if (CurPhoneIdx > -1) {
strcpy (buf, PhoneBook[CurPhoneIdx]->Number);
edit->Set_Text (buf, PhoneEntryClass::PHONE_MAX_NUM );
list->Set_Selected_Index( CurPhoneIdx );
}
}
/***************************************************************************
* Phone_Compare -- for qsort *
* *
* INPUT: *
* p1,p2 ptrs to elements to compare *
* *
* OUTPUT: *
* 0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2) *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=========================================================================*/
static int Phone_Compare (const void *p1, const void *p2)
{
class PhoneEntryClass *pe1,*pe2;
int result;
pe1 = *((class PhoneEntryClass **)p1);
pe2 = *((class PhoneEntryClass **)p2);
result = strcmp( pe1->Name, pe2->Name );
// if strings are equal then check the phone number
if ( !result ) {
result = strcmp( pe1->Number, pe2->Number );
}
return(result);
}
/***************************************************************************
* Edit_Phone_Dialog -- lets user edit a phone book entry *
* *
* INPUT: *
* phone entry to edit *
* *
* OUTPUT: *
* true = OK, false = cancel *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 04/29/1995 BRR : Created. *
*=========================================================================*/
static int Edit_Phone_Dialog (PhoneEntryClass *phone)
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 230 *factor; // dialog width
int d_dialog_h = 105*factor; // dialog height
int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
// D_DIALOG_Y = ((200 - D_DIALOG_H) / 2); // dialog y-coord
int d_dialog_y = ((136*factor - d_dialog_h) / 2); // dialog y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
int d_txt6_h = 11 *factor; // ht of 6-pt text
int d_margin = 7 *factor; // margin width/height
int d_name_w = ( (PhoneEntryClass::PHONE_MAX_NAME - 1) * 6) + 3 *factor;
int d_name_h = 9 *factor;
int d_name_x = d_dialog_x + (((d_dialog_w - d_name_w) * 3) / 4) - 5 *factor;
int d_name_y = d_dialog_y + 25 *factor;
int d_number_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) + 3 *factor;
int d_number_h = 9 *factor;
int d_number_x = d_dialog_x + (((d_dialog_w - d_number_w) * 3) / 4) - 5 *factor;
int d_number_y = d_name_y + d_name_h + d_margin;
#if (GERMAN | FRENCH)
int d_default_w = 130 *factor;
#else
int d_default_w = 104 *factor;
#endif
int d_default_h = 9 *factor;
int d_default_x = d_dialog_cx - (d_default_w / 2);
int d_default_y = d_number_y + d_number_h + d_margin;
#if (GERMAN | FRENCH)
int d_custom_w = 130 *factor;
#else
int d_custom_w = 100 *factor;
#endif
int d_custom_h = 9 *factor;
int d_custom_x = d_dialog_cx - (d_default_w / 2);
int d_custom_y = d_default_y + d_default_h + d_margin;
#if (GERMAN | FRENCH)
int d_save_w = 55 *factor;
#else
int d_save_w = 45 *factor;
#endif
int d_save_h = 9 *factor;
int d_save_x = d_dialog_cx - d_margin - d_save_w;
int d_save_y = d_dialog_y + d_dialog_h - d_margin - d_save_h;
#if (GERMAN | FRENCH)
int d_cancel_w = 55 *factor;
#else
int d_cancel_w = 45 *factor;
#endif
int d_cancel_h = 9 *factor;
int d_cancel_x = d_dialog_cx + d_margin;
int d_cancel_y = d_dialog_y + d_dialog_h - d_margin - d_cancel_h;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_NAME = 100,
BUTTON_NUMBER,
BUTTON_DEFAULT,
BUTTON_CUSTOM,
BUTTON_SAVE,
BUTTON_CANCEL,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display = REDRAW_ALL; // redraw level
BOOL process = true; // process while true
KeyNumType input;
char namebuf[PhoneEntryClass::PHONE_MAX_NAME] = { 0 }; // buffer for editing name
char numbuf[PhoneEntryClass::PHONE_MAX_NUM] = { 0 }; // buffer for editing phone #
int rc;
SerialSettingsType settings;
int custom = 0;
int firsttime = 1;
/*........................................................................
Buttons
........................................................................*/
GadgetClass *commands; // button list
EditClass nameedit (BUTTON_NAME,
namebuf, PhoneEntryClass::PHONE_MAX_NAME,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
EditClass numedit (BUTTON_NUMBER,
numbuf, PhoneEntryClass::PHONE_MAX_NUM,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_number_x, d_number_y, d_number_w, d_number_h, EditClass::ALPHANUMERIC);
TextButtonClass defaultbtn(BUTTON_DEFAULT, TXT_DEFAULT_SETTINGS,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_default_x, d_default_y, d_default_w, d_default_h);
TextButtonClass custombtn(BUTTON_CUSTOM, TXT_CUSTOM_SETTINGS,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_custom_x, d_custom_y, d_custom_w, d_custom_h);
TextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_save_x, d_save_y, d_save_w, d_save_h);
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
/*
------------------------- Build the button list --------------------------
*/
commands = &nameedit;
numedit.Add_Tail(*commands);
defaultbtn.Add_Tail(*commands);
custombtn.Add_Tail(*commands);
savebtn.Add_Tail(*commands);
cancelbtn.Add_Tail(*commands);
/*
----------------------------- Various Inits ------------------------------
*/
/*........................................................................
Init the settings; if the phone entry is set to use defaults, init our
settings to sensible values (in case we invoke the setting editor);
otherwise, copy the entry's settings.
........................................................................*/
if (phone->Settings.Port == 0 || phone->Settings.IRQ == -1 ||
phone->Settings.Baud == -1) {
settings = SerialDefaults;
defaultbtn.Turn_On();
custom = false;
} else {
settings = phone->Settings;
custombtn.Turn_On();
custom = true;
}
strcpy (namebuf, phone->Name);
nameedit.Set_Text (namebuf, PhoneEntryClass::PHONE_MAX_NAME);
strcpy (numbuf, phone->Number);
numedit.Set_Text (numbuf, PhoneEntryClass::PHONE_MAX_NUM);
/*
---------------------------- Processing loop -----------------------------
*/
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
if (display >= REDRAW_BACKGROUND) {
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
// init font variables
Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*...............................................................
Dialog & Field labels
...............................................................*/
Draw_Caption (TXT_PHONE_LISTING, d_dialog_x, d_dialog_y, d_dialog_w);
Fancy_Text_Print (TXT_NAME_COLON,
d_name_x - 5, d_name_y + 1,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
Fancy_Text_Print (TXT_NUMBER_COLON,
d_number_x - 5, d_number_y + 1,
CC_GREEN, TBLACK,
TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
commands->Flag_List_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
if ( firsttime ) {
nameedit.Set_Focus();
nameedit.Flag_To_Redraw();
input = commands->Input();
firsttime = 0;
}
/*
---------------------------- Process input ----------------------------
*/
switch (input) {
case (BUTTON_NAME | KN_BUTTON):
numedit.Set_Focus();
numedit.Flag_To_Redraw();
break;
// case (BUTTON_NUMBER | KN_BUTTON):
// nameedit.Clear_Focus();
// nameedit.Flag_To_Redraw();
// break;
/*------------------------------------------------------------------
Use Default Serial Settings
------------------------------------------------------------------*/
case (BUTTON_DEFAULT | KN_BUTTON):
custombtn.Turn_Off();
defaultbtn.Turn_On();
custom = 0;
break;
/*------------------------------------------------------------------
Use Custom Serial Settings
------------------------------------------------------------------*/
case (BUTTON_CUSTOM | KN_BUTTON):
if (Com_Settings_Dialog (&settings)) {
custombtn.Turn_On();
defaultbtn.Turn_Off();
}
custom = 1;
display = REDRAW_ALL;
break;
/*------------------------------------------------------------------
CANCEL: bail out
------------------------------------------------------------------*/
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
/*------------------------------------------------------------------
Save: save changes
------------------------------------------------------------------*/
case (KN_RETURN):
case (BUTTON_SAVE | KN_BUTTON):
process = false;
rc = true;
break;
}
} /* end of while */
/*------------------------------------------------------------------------
If 'Save', save all current settings
------------------------------------------------------------------------*/
if (rc) {
strcpy( phone->Name, strupr( namebuf ) );
// if nothing was entered then make if NONAME
if ( !(phone->Name[0]) ) {
strcpy( phone->Name, "NONAME" );
}
strcpy( phone->Number, strupr( numbuf ) );
if (custom) {
phone->Settings = settings;
} else {
phone->Settings.Port = 0;
phone->Settings.IRQ = -1;
phone->Settings.Baud = -1;
phone->Settings.DialMethod = DIAL_TOUCH_TONE;
phone->Settings.InitStringIndex = 0;
phone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;
phone->Settings.CallWaitString[0] = 0;
}
}
return(rc);
} /* end of Edit_Phone_Dialog */
static bool Dial_Modem( SerialSettingsType *settings, bool reconnect )
{
bool connected = false;
DialStatusType dialstatus;
int modemstatus;
/*
** Turn modem servicing off in the callback routine.
*/
ModemService = false;
// save for later to reconnect
DialSettings = settings;
modemstatus = NullModem.Get_Modem_Status();
if (reconnect) {
if ( (modemstatus & CD_SET) ) {
connected = true;
ModemService = true;
return( connected );
}
} else {
if ( (modemstatus & CD_SET) ) {
NullModem.Hangup_Modem();
ModemService = false;
}
}
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
#if (0)
/*
** If our first attempt to detect the modem failed, and we're at
** 14400 or 28800, bump up to the next baud rate & try again.
*/
switch (settings->Baud) {
case 9600:
case 19200:
case 38400:
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
case 14400:
settings->Baud = 19200;
Shutdown_Modem();
Init_Null_Modem(settings);
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
}
break;
case 28800:
settings->Baud = 38400;
Shutdown_Modem();
Init_Null_Modem(settings);
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
}
break;
}
#else //(0)
ModemService = true;
return( connected );
#endif //(0)
}
else if ( modemstatus == -1 ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
CCMessageBox().Process( TXT_ERROR_IN_INITSTRING );
// CCMessageBox().Process( "Error in the InitString." );
ModemService = true;
return( connected );
}
dialstatus = NullModem.Dial_Modem( DialString, settings->DialMethod, reconnect );
if (reconnect) {
/*
--------------------------- Redraw the display ---------------------------
*/
HiddenPage.Clear();
Map.Flag_To_Redraw(true);
Map.Render();
}
switch ( dialstatus ) {
case DIAL_CONNECTED:
connected = true;
break;
case DIAL_NO_CARRIER:
CCMessageBox().Process(TXT_NO_CARRIER);
connected = false;
break;
case DIAL_BUSY:
CCMessageBox().Process(TXT_LINE_BUSY);
connected = false;
break;
case DIAL_ERROR:
CCMessageBox().Process(TXT_NUMBER_INVALID);
connected = false;
break;
case DIAL_CANCELED:
NullModem.Hangup_Modem();
ModemService = false;
CCMessageBox().Process(TXT_DIALING_CANCELED);
connected = false;
break;
}
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
ModemService = true;
return( connected );
} /* end of Dial_Modem */
static bool Answer_Modem( SerialSettingsType *settings, bool reconnect )
{
bool connected = false;
DialStatusType dialstatus;
int modemstatus;
/* ###Change collision detected! C:\PROJECTS\CODE\NULLDLG.CPP... */
/*
** Turn modem servicing off in the callback routine.
*/
ModemService = false;
// save for later to reconnect
DialSettings = settings;
modemstatus = NullModem.Get_Modem_Status();
if (reconnect) {
if ( (modemstatus & CD_SET) ) {
connected = true;
ModemService = true;
return( connected );
}
} else {
if ( (modemstatus & CD_SET) ) {
NullModem.Hangup_Modem();
ModemService = false;
}
}
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
#if (0)
/*
** If our first attempt to detect the modem failed, and we're at
** 14400 or 28800, bump up to the next baud rate & try again.
*/
switch (settings->Baud) {
case 9600:
case 19200:
case 38400:
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
case 14400:
settings->Baud = 19200;
Shutdown_Modem();
Init_Null_Modem(settings);
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
}
break;
case 28800:
settings->Baud = 38400;
Shutdown_Modem();
Init_Null_Modem(settings);
NullModem.Setup_Modem_Echo( Modem_Echo );
modemstatus = NullModem.Detect_Modem( settings, reconnect );
if ( !modemstatus ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
//CCMessageBox().Process( TXT_UNABLE_FIND_MODEM );
ModemService = true;
return( connected );
}
break;
}
#else //(0)
ModemService = true;
return( connected );
#endif //(0)
}
else if ( modemstatus == -1 ) {
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
CCMessageBox().Process( TXT_ERROR_IN_INITSTRING );
ModemService = true;
return( connected );
}
dialstatus = NullModem.Answer_Modem( reconnect );
switch ( dialstatus ) {
case DIAL_CONNECTED:
connected = true;
break;
case DIAL_NO_CARRIER:
CCMessageBox().Process(TXT_NO_CARRIER);
connected = false;
break;
// case DIAL_BUSY:
// CCMessageBox().Process(TXT_LINE_BUSY);
// connected = false;
// break;
case DIAL_ERROR:
// Error occurred but not neccessarily an invalid number
//CCMessageBox().Process(TXT_NUMBER_INVALID);
connected = false;
break;
case DIAL_CANCELED:
CCMessageBox().Process(TXT_ANSWERING_CANCELED);
connected = false;
break;
}
NullModem.Remove_Modem_Echo();
NullModem.Print_EchoBuf();
NullModem.Reset_EchoBuf();
ModemService = true;
return( connected );
} /* end of Answer_Modem */
static void Modem_Echo( char c )
{
if (NullModem.EchoCount < (NullModem.EchoSize - 1) ) {
*(NullModem.EchoBuf + NullModem.EchoCount) = c;
*(NullModem.EchoBuf + NullModem.EchoCount + 1) = 0;
NullModem.EchoCount++;
} else {
//Smart_Printf( "Echo buffer full!!!\n" );
}
} /* end of Modem_Echo */
void Smart_Printf( char *format, ... )
{
va_list arglist;
char buf[501];
va_start(arglist,format);
vsprintf(buf,format,arglist);
va_end(arglist);
if (Debug_Smart_Print) {
if (Special.IsMonoEnabled) {
// Mono_Set_Cursor(0,0);
Mono_Printf("%s",buf);
} else {
// Mono_Printf("%s",buf);
printf("%s",buf);
}
} else {
if (Debug_Heap_Dump) {
printf("%s",buf);
}
}
}
void Hex_Dump_Data( char *buffer, int length )
{
int i;
int offset = 0;
char buff[10];
char ptr[16];
char c;
while (length >= 16) {
memcpy( ptr, (buffer + offset), 16);
Smart_Printf("%05lX ", offset);
for (i = 0; i < 16; i++) {
c = ptr[i];
itoh(c, buff);
if (!(i & 0x3) && i) {
Smart_Printf("?");
}
Smart_Printf("%s ", buff);
}
Smart_Printf(" ");
for (i = 0; i < 16; i++) {
c = ptr[i];
if (c && ((c < 7) || (c > 11)) && (c != 13)) {
Smart_Printf("%c", c);
} else {
Smart_Printf(".");
}
}
Smart_Printf("\n");
offset += 16;
length -= 16;
}
if (length) {
memcpy( ptr, (buffer + offset), 16);
Smart_Printf("%05lX ", offset);
for (i = 0; i < 16; i++) {
if (i < length) {
c = ptr[i];
itoh(c, buff);
if (!(i & 0x3) && i) {
Smart_Printf("?");
}
Smart_Printf("%s ", buff);
} else {
if (!(i & 0x3) && i) {
Smart_Printf(" ");
}
Smart_Printf(" ");
}
}
Smart_Printf(" ");
for (i = 0; i < length; i++) {
c = ptr[i];
if (c && ((c < 7) || (c > 11)) && (c != 13)) {
Smart_Printf("%c", c);
} else {
Smart_Printf(".");
}
}
Smart_Printf("\n");
}
} /* end of Hex_Dump_Data */
void itoh( int i, char *s)
{
int nibble, loop;
// *s++ = '0';
// *s++ = 'x';
if (i == 0) {
*s++ = '0';
*s++ = '0';
} else {
for (loop = 1; loop >= 0; loop--) {
nibble = (i >> (loop << 2)) & 0x000F;
/* decimal range */
if (nibble < 10) {
*s++ = '0' + nibble;
} else {
*s++ = 'A' + (nibble - 10);
}
}
}
*s = 0; /* null terminate it */
}
#if (0)
int Com_Fake_Scenario_Dialog(void)
{
bool display = true; // redraw level
bool process = true; // process while true
char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
int transmit; // 1 = re-transmit new game options
int parms_received = 1; // 1 = game options received
int changed = 0; // 1 = user has changed an option
int rc;
int recsignedoff = false;
int version;
unsigned long starttime;
unsigned long timingtime;
unsigned long lastmsgtime;
unsigned long lastredrawtime;
unsigned long transmittime = 0;
unsigned long theirresponsetime;
int packetlen;
bool oppscorescreen = false;
bool gameoptions = false;
EventClass *event; // event ptr
unsigned long msg_timeout = 60*60; // init to 60 seconds
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_CANCEL = 100,
};
/*........................................................................
Dialog variables
........................................................................*/
TextButtonClass * buttons = 0;
KeyNumType input;
int x,y;
int width=0;
int height=0;
char text_buffer[80*3];
const char *current_status_string = Text_String(TXT_WINSOCK_CONNECTING);
strcpy(text_buffer, current_status_string);
Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
width = MAX(width, 50*factor);
width += 40*factor;
height += 60*factor;
x = (SeenBuff.Get_Width() - width) / 2;
y = (SeenBuff.Get_Height() - height) / 2;
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8*factor)) >> 1),
y + height - (FontHeight + FontYSpacing + 2*factor) - 5*factor);
Set_Logic_Page(SeenBuff);
buttons = &cancelbtn;
buttons->Flag_List_To_Redraw();
process = true;
/*........................................................................
Init other scenario parameters
........................................................................*/
Special.IsTGrowth = MPlayerTiberium;
Special.IsTSpread = MPlayerTiberium;
transmit = 1;
/*........................................................................
Init random-number generator, & create a seed to be used for all random
numbers from here on out
........................................................................*/
randomize();
//Seed = rand();
/*
---------------------------- Processing loop -----------------------------
*/
NullModem.Reset_Response_Time(); // clear response time
theirresponsetime = 10000; // initialize to an invalid value
timingtime = lastmsgtime = lastredrawtime = TickCount.Time();
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=true;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
/*
..................... Draw the background .......................
*/
Dialog_Box(x, y, width, height);
/*
....................... Draw the labels .........................
*/
Draw_Caption(TXT_NONE, x, y, width);
Fancy_Text_Print(text_buffer, x + 20*factor, y + 25*factor, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
buttons->Draw_All();
Show_Mouse();
display = false;
}
/*
............................ Process input ............................
*/
input = buttons->Input();
switch (input) {
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
default:
break;
}
/*---------------------------------------------------------------------
If our Transmit flag is set, we need to send out a game option packet.
This message requires an ACK. The first time through the loop, transmit
should be set, so we send out our default options; we'll then send
any changes we make to the defaults.
---------------------------------------------------------------------*/
if (transmit && (TickCount.Time() - transmittime) > PACKET_RETRANS_TIME) {
SendPacket.Command = SERIAL_GAME_OPTIONS;
strcpy (SendPacket.Name, MPlayerName);
#ifdef PATCH
if (IsV107) {
SendPacket.Version = 1;
} else {
SendPacket.Version = 2;
}
#else
SendPacket.Version = Version_Number();
#endif
SendPacket.House = MPlayerHouse;
SendPacket.Color = MPlayerColorIdx;
SendPacket.Scenario = MPlayerFilenum[ScenarioIdx];
SendPacket.Credits = MPlayerCredits;
SendPacket.IsBases = MPlayerBases;
SendPacket.IsTiberium = MPlayerTiberium;
SendPacket.IsGoodies = MPlayerGoodies;
SendPacket.IsGhosties = MPlayerGhosts;
SendPacket.BuildLevel = BuildLevel;
SendPacket.UnitCount = MPlayerUnitCount;
SendPacket.Seed = Seed;
SendPacket.Special = Special;
SendPacket.GameSpeed = Options.GameSpeed;
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
transmittime = TickCount.Time();
transmit = 0;
}
//
// send a timing packet if enough time has gone by.
//
if ( (TickCount.Time() - timingtime) > PACKET_TIMING_TIMEOUT) {
SendPacket.Command = SERIAL_TIMING;
SendPacket.ResponseTime = NullModem.Response_Time();
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);
timingtime = TickCount.Time();
}
/*---------------------------------------------------------------------
Check for an incoming message
---------------------------------------------------------------------*/
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
lastmsgtime = TickCount.Time();
msg_timeout = 600; // reset timeout value to 10 seconds
// (only the 1st time through is 20 seconds)
if (ReceivePacket.Command >= SERIAL_CONNECT &&
ReceivePacket.Command < SERIAL_LAST_COMMAND &&
ReceivePacket.Command != SERIAL_MESSAGE &&
ReceivePacket.ID == ModemGameToPlay) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
break;
}
event = (EventClass *)&ReceivePacket;
if (event->Type <= EventClass::FRAMEINFO) {
if ( (TickCount.Time() - lastredrawtime) > PACKET_REDRAW_TIME) {
lastredrawtime = TickCount.Time();
oppscorescreen = true;
parms_received = 1;
}
} else {
switch ( ReceivePacket.Command ) {
/*..................................................................
Sign-off: Give the other machine time to receive my ACK, display a
message, and exit.
..................................................................*/
case (SERIAL_SIGN_OFF):
starttime = TickCount.Time();
while (TickCount.Time() - starttime < 60)
NullModem.Service();
CCMessageBox().Process(TXT_USER_SIGNED_OFF);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
recsignedoff = true;
break;
/*..................................................................
Game Options: Store the other machine's name, color & house;
If they've picked the same color as myself, re-transmit my settings
to force him to choose a different color. (Com_Show_Scenario_Dialog
is responsible for ensuring the colors are different.)
..................................................................*/
case (SERIAL_GAME_OPTIONS):
oppscorescreen = false;
gameoptions = true;
strcpy (TheirName, ReceivePacket.Name);
TheirColor = ReceivePacket.Color;
TheirHouse = ReceivePacket.House;
transmit = 1;
parms_received = 1;
/*...............................................................
Check the version number of the other system.
...............................................................*/
#ifdef PATCH
if (IsV107) {
version = 1;
} else {
version = 2;
}
#else
version = Version_Number();
#endif
if (ReceivePacket.Version > version) {
CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
} else {
if (ReceivePacket.Version < version) {
CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
}
}
break;
/*..................................................................
Incoming message: add to our list
..................................................................*/
//
// get their response time
//
case (SERIAL_TIMING):
oppscorescreen = false;
theirresponsetime = ReceivePacket.ResponseTime;
if ( !gameoptions ) {
transmit = 1;
}else{
process = false;
rc = true;
}
break;
//
// print msg waiting for opponent
//
case (SERIAL_SCORE_SCREEN):
oppscorescreen = true;
parms_received = 1;
break;
default:
break;
}
}
}
// if we haven't received a msg for 10 seconds exit
if ( (TickCount.Time() - lastmsgtime) > msg_timeout) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
}
/*---------------------------------------------------------------------
Service the connection
---------------------------------------------------------------------*/
NullModem.Service();
} /* end of while */
/*------------------------------------------------------------------------
Sort player ID's, so we can execute commands in the same order on both
machines.
------------------------------------------------------------------------*/
if (rc) {
/*.....................................................................
Set the number of players in this game, and my ID
.....................................................................*/
MPlayerCount = 2;
MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
TheirID = Build_MPlayerID (TheirColor,TheirHouse);
/*.....................................................................
Store every player's ID in the MPlayerID[] array. This array will
determine the order of event execution, so the ID's must be stored
in the same order on all systems.
.....................................................................*/
if (TheirID < MPlayerLocalID) {
MPlayerID[0] = TheirID;
MPlayerID[1] = MPlayerLocalID;
strcpy (MPlayerNames[0], TheirName);
strcpy (MPlayerNames[1], MPlayerName);
} else {
MPlayerID[0] = MPlayerLocalID;
MPlayerID[1] = TheirID;
strcpy (MPlayerNames[0], MPlayerName);
strcpy (MPlayerNames[1], TheirName);
}
/*.....................................................................
Get the scenario filename
.....................................................................*/
Scenario = MPlayerFilenum[ScenarioIdx];
/*.....................................................................
Send all players the GO packet.
.....................................................................*/
SendPacket.Command = SERIAL_GO;
SendPacket.ResponseTime = NullModem.Response_Time();
if ( theirresponsetime == 10000 ) {
// Mono_Clear_Screen();
// Smart_Printf( "Did not receive their response time!!!!!!!\n" );
// Get_Key();
} else {
if (SendPacket.ResponseTime < theirresponsetime) {
SendPacket.ResponseTime = theirresponsetime;
}
}
//
// calculated one way delay for a packet and overall delay to execute
// a packet
//
////////MPlayerMaxAhead = MAX( (SendPacket.ResponseTime / 8), 2);
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( ( NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_SENDING_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
NullModem.Service();
Keyboard::Check(); //Make sure the message loop gets called
}
// clear queue to keep from doing any resends
NullModem.Init_Send_Queue();
} else {
if ( !recsignedoff ) {
/*.....................................................................
Broadcast my sign-off over my network
.....................................................................*/
SendPacket.Command = SERIAL_SIGN_OFF;
SendPacket.Color = MPlayerLocalID; // use Color for ID
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( (NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_CANCEL_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {
// are we getting our own packets back??
if (ReceivePacket.Command == SERIAL_SIGN_OFF
&& ReceivePacket.ID == ModemGameToPlay) {
// exit while
break;
}
}
NullModem.Service();
}
}
Shutdown_Modem();
}
/*------------------------------------------------------------------------
Restore screen
------------------------------------------------------------------------*/
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Show_Mouse();
/*------------------------------------------------------------------------
Save any changes made to our options
------------------------------------------------------------------------*/
if (changed) {
Write_MultiPlayer_Settings ();
}
return(rc);
} /* end of Com_Scenario_Dialog */
int Com_Show_Fake_Scenario_Dialog(void)
{
/*........................................................................
Dialog variables
........................................................................*/
bool display = true; // redraw level
BOOL process = true; // process while true
char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
int transmit; // 1 = re-transmit new game options
int first; // 1 = no packets received yet
int parms_received = 0; // 1 = game options received
int changed = 0; // 1 = user has changed an option
int rc;
int recsignedoff = 0;
int i;
int version;
unsigned long starttime;
unsigned long timingtime;
unsigned long lastmsgtime;
unsigned long lastredrawtime;
unsigned long transmittime = 0;
int packetlen;
bool oppscorescreen = false;
bool gameoptions = false;
EventClass *event; // event ptr
unsigned long msg_timeout = 60*60; // init to 60 seconds
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Button Enumerations
........................................................................*/
enum {
BUTTON_CANCEL = 100,
};
/*........................................................................
Dialog variables
........................................................................*/
TextButtonClass * buttons = 0;
KeyNumType input;
int x,y;
int width=0;
int height=0;
char text_buffer[80*3];
const char *current_status_string = Text_String(TXT_WINSOCK_CONNECTING);
strcpy(text_buffer, current_status_string);
Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
width = MAX(width, 50*factor);
width += 40*factor;
height += 60*factor;
x = (SeenBuff.Get_Width() - width) / 2;
y = (SeenBuff.Get_Height() - height) / 2;
TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8*factor)) >> 1),
y + height - (FontHeight + FontYSpacing + 2*factor) - 5*factor);
Set_Logic_Page(SeenBuff);
buttons = &cancelbtn;
buttons->Flag_List_To_Redraw();
transmit = 1;
first = 1;
/*
---------------------------- Processing loop -----------------------------
*/
NullModem.Reset_Response_Time(); // clear response time
timingtime = lastmsgtime = lastredrawtime = TickCount.Time();
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=true;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
/*
.................. Redraw backgound & dialog box ...................
*/
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
HidPage.Blit(SeenBuff);
Set_Palette(Palette);
/*
..................... Draw the background .......................
*/
Dialog_Box(x, y, width, height);
/*
....................... Draw the labels .........................
*/
Draw_Caption(TXT_NONE, x, y, width);
Fancy_Text_Print(text_buffer, x + 20*factor, y + 25*factor, CC_GREEN, TBLACK,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
buttons->Draw_All();
Show_Mouse();
display = false;
}
/*
............................ Process input ............................
*/
input = buttons->Input();
switch (input) {
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
process = false;
rc = false;
break;
default:
break;
}
/*---------------------------------------------------------------------
If our Transmit flag is set, we need to send out a game option packet
---------------------------------------------------------------------*/
if (transmit && (TickCount.Time() - transmittime) > PACKET_RETRANS_TIME) {
SendPacket.Command = SERIAL_GAME_OPTIONS;
strcpy (SendPacket.Name, MPlayerName);
#ifdef PATCH
if (IsV107) {
SendPacket.Version = 1;
} else {
SendPacket.Version = 2;
}
#else
SendPacket.Version = Version_Number();
#endif
SendPacket.House = MPlayerHouse;
SendPacket.Color = MPlayerColorIdx;
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
transmittime = TickCount.Time();
transmit = 0;
}
//
// send a timing packet if enough time has gone by.
//
if ( (TickCount.Time() - timingtime) > PACKET_TIMING_TIMEOUT) {
SendPacket.Command = SERIAL_TIMING;
SendPacket.ResponseTime = NullModem.Response_Time();
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0);
timingtime = TickCount.Time();
}
/*---------------------------------------------------------------------
Check for an incoming message
---------------------------------------------------------------------*/
if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) {
lastmsgtime = TickCount.Time();
msg_timeout = 600;
// are we getting our own packets back??
if (ReceivePacket.Command >= SERIAL_CONNECT &&
ReceivePacket.Command < SERIAL_LAST_COMMAND &&
ReceivePacket.Command != SERIAL_MESSAGE &&
ReceivePacket.ID == ModemGameToPlay) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
break;
}
event = (EventClass *)&ReceivePacket;
if (event->Type <= EventClass::FRAMEINFO) {
if ( (TickCount.Time() - lastredrawtime) > PACKET_REDRAW_TIME) {
lastredrawtime = TickCount.Time();
oppscorescreen = true;
display = false;
parms_received = 1;
}
} else {
switch ( ReceivePacket.Command ) {
/*..................................................................
Other system signs off: Give it time to receive my ACK, then show
a message.
..................................................................*/
case (SERIAL_SIGN_OFF):
starttime = TickCount.Time();
while ( (TickCount.Time() - starttime) < 60)
NullModem.Service();
CCMessageBox().Process(TXT_USER_SIGNED_OFF);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
recsignedoff = true;
break;
/*..................................................................
Game Options: Store all options; check my color & game version.
..................................................................*/
case (SERIAL_GAME_OPTIONS):
oppscorescreen = false;
gameoptions = true;
display = false;
parms_received = 1;
strcpy (TheirName, ReceivePacket.Name);
TheirColor = ReceivePacket.Color;
TheirHouse = ReceivePacket.House;
/*...............................................................
Save scenario settings.
...............................................................*/
MPlayerCredits = ReceivePacket.Credits;
MPlayerBases = ReceivePacket.IsBases;
MPlayerTiberium = ReceivePacket.IsTiberium;
MPlayerGoodies = ReceivePacket.IsGoodies;
MPlayerGhosts = ReceivePacket.IsGhosties;
BuildLevel = ReceivePacket.BuildLevel;
MPlayerUnitCount = ReceivePacket.UnitCount;
Seed = ReceivePacket.Seed;
Special = ReceivePacket.Special;
Options.GameSpeed = ReceivePacket.GameSpeed;
if (MPlayerTiberium) {
Special.IsTGrowth = 1;
Special.IsTSpread = 1;
} else {
Special.IsTGrowth = 0;
Special.IsTSpread = 0;
}
/*...............................................................
Find the index of the scenario number; if it's not found, leave
it at -1.
...............................................................*/
ScenarioIdx = -1;
for (i = 0; i < MPlayerFilenum.Count(); i++) {
if (ReceivePacket.Scenario == MPlayerFilenum[i])
ScenarioIdx = i;
}
/*...............................................................
Check our version numbers; if they're incompatible, sign off.
...............................................................*/
#ifdef PATCH
if (IsV107) {
version = 1;
} else {
version = 2;
}
#else
version = Version_Number();
#endif
if (ReceivePacket.Version > version) {
CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
} else {
if (ReceivePacket.Version < version) {
CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
// to skip the other system not responding msg
lastmsgtime = TickCount.Time();
process = false;
rc = false;
}
}
/*...............................................................
If this is the first game-options packet we've received, transmit
our options to him.
...............................................................*/
if (first) {
first = 0;
// force transmitting of game options packet
transmit = 1;
transmittime = 0;
}
break;
/*..................................................................
GO: Exit this routine with a success code.
..................................................................*/
case (SERIAL_GO):
//
// calculated one way delay for a packet and overall delay
// to execute a packet
//
////////MPlayerMaxAhead = MAX( (ReceivePacket.ResponseTime / 8), 2);
process = false;
rc = true;
break;
//
// throw away timing packet
//
case (SERIAL_TIMING):
oppscorescreen = false;
break;
//
// print msg waiting for opponent
//
case (SERIAL_SCORE_SCREEN):
// Smart_Printf( "received score screen\n" );
oppscorescreen = true;
display = false;
parms_received = 1;
break;
default:
break;
}
}
}
// if we haven't received a msg for 10 seconds exit
if ( (TickCount.Time() - lastmsgtime) > msg_timeout) {
CCMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
process = false;
rc = false;
// say we did receive sign off to keep from sending one
recsignedoff = true;
}
/*---------------------------------------------------------------------
Service the connection
---------------------------------------------------------------------*/
NullModem.Service();
} /* end of while */
/*------------------------------------------------------------------------
Sort player ID's, so we can execute commands in the same order on both
machines.
------------------------------------------------------------------------*/
if (rc) {
/*.....................................................................
Set the number of players in this game, and my ID
.....................................................................*/
MPlayerCount = 2;
MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
TheirID = Build_MPlayerID (TheirColor,TheirHouse);
/*.....................................................................
Store every player's ID in the MPlayerID[] array. This array will
determine the order of event execution, so the ID's must be stored
in the same order on all systems.
.....................................................................*/
if (TheirID < MPlayerLocalID) {
MPlayerID[0] = TheirID;
MPlayerID[1] = MPlayerLocalID;
strcpy (MPlayerNames[0], TheirName);
strcpy (MPlayerNames[1], MPlayerName);
} else {
MPlayerID[0] = MPlayerLocalID;
MPlayerID[1] = TheirID;
strcpy (MPlayerNames[0], MPlayerName);
strcpy (MPlayerNames[1], TheirName);
}
/*.....................................................................
Get the scenario filename
.....................................................................*/
Scenario = MPlayerFilenum[ScenarioIdx];
starttime = TickCount.Time();
while ( ( NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_SENDING_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
NullModem.Service();
Keyboard::Check(); //Make sure the message loop gets called
}
// clear queue to keep from doing any resends
NullModem.Init_Send_Queue();
} else {
if ( !recsignedoff ) {
/*.....................................................................
Broadcast my sign-off over my network
.....................................................................*/
SendPacket.Command = SERIAL_SIGN_OFF;
SendPacket.Color = MPlayerLocalID; // use Color for ID
SendPacket.ID = ModemGameToPlay;
NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1);
starttime = TickCount.Time();
while ( (NullModem.Num_Send()
&& ((TickCount.Time() - starttime) < PACKET_CANCEL_TIMEOUT) )
|| ((TickCount.Time() - starttime) < 60) ) {
#if(SHOW_MONO)
NullModem.Mono_Debug_Print(0);
#endif
if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) {
// are we getting our own packets back??
if (ReceivePacket.Command == SERIAL_SIGN_OFF
&& ReceivePacket.ID == ModemGameToPlay) {
// exit while
break;
}
}
NullModem.Service();
}
}
Shutdown_Modem();
}
/*------------------------------------------------------------------------
Save any changes made to our options
------------------------------------------------------------------------*/
if (changed) {
Write_MultiPlayer_Settings ();
}
return(rc);
} /* end of Com_Show_Scenario_Dialog */
#endif //(0)