// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* $Header: /counterstrike/NULLDLG.CPP 14 3/17/97 1:05a Steve_tall $ */ /*************************************************************************** ** 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 : Jan. 21, 1997 [V.Grippi] * * * *-------------------------------------------------------------------------* * Functions: * * Build_InitString_Listbox -- [re]builds the initstring entry listbox * * Build_Phone_Listbox -- [re]builds the phone entry listbox * * Com_Scenario_Dialog -- Serial game scenario selection dialog * * Com_Settings_Dialog -- Lets user select serial port settings * * Destroy_Null_Connection -- destroys the given connection * * Edit_Phone_Dialog -- lets user edit a phone book entry * * Init_Null_Modem -- Initializes Null Modem communications * * Init_String_Compare -- for qsort * * Phone_Compare -- for qsort * * Phone_Dialog -- Lets user edit phone directory & dial * * Reconnect_Null_Modem -- allows user to reconnect * * Select_Serial_Dialog -- Serial Communications menu dialog * * Shutdown_Modem -- Shuts down modem/null-modem communications * * Test_Null_Modem -- Null-Modem test routine * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" //PG GameType Select_Serial_Dialog(void) { return GAME_NORMAL; } #if (0)//PG #ifdef FIXIT_RANDOM_GAME #include "time.h" #endif #ifdef WIN32 #include "wincomm.h" #include "modemreg.h" ModemRegistryEntryClass *ModemRegistry = NULL; //Ptr to modem registry data #endif //WIN32 #include "COORDA.h" #ifdef FIXIT_CSII // checked - ajw 9/28/98 extern bool Is_Mission_126x126 (char *file_name); extern bool Is_Mission_Counterstrike (char *file_name); extern bool Is_Mission_Aftermath( char* file_name ); #endif //#include "WolDebug.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 //extern char const *ForMisStr[]; extern char const *EngMisStr[]; // // 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]; PlayerColorType TheirColor; HousesType TheirHouse; static char DialString[ CWAITSTRBUF_MAX + PhoneEntryClass::PHONE_MAX_NUM - 1 ]; static SerialSettingsType *DialSettings; #ifdef FIXIT_VERSION_3 bool Force_Scenario_Available( const char* szName ); bool bSpecialAftermathScenario( const char* szScenarioDescription ); #endif #define PCOLOR_BROWN PCOLOR_GREY #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. * * 8/2/96 ST : Win32 support added * *=========================================================================*/ int Init_Null_Modem( SerialSettingsType *settings ) { #ifdef WIN32 if ( NullModem.Init( settings->Port, settings->IRQ, settings->ModemName, settings->Baud, 0, 8, 1, settings->HardwareFlowControl ) ) { return (true); } else { return (false); } #else //WIN32 if ( NullModem.Init( settings->Port, settings->IRQ, settings->ModemName, settings->Baud, 'N', 8, 1, settings->HardwareFlowControl) ) { NullModem.Change_IRQ_Priority( settings->IRQ ); return(true); } else { return(false); } #endif //WIN32 } /*************************************************************************** * 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 (!Session.Play) { if (Session.Type == 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 (!Session.Play) { /* ** Send a sign-off packet */ memset (&event, 0, sizeof(EventClass)); event.Type = EventClass::EXIT; NullModem.Send_Message (&event,sizeof(EventClass),0); NullModem.Send_Message (&event,sizeof(EventClass),0); starttime = TickCount; while ( (TickCount - 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. * * 8/2/96 ST : Win32 support added * *=========================================================================*/ int Test_Null_Modem( void ) { /* ** Get the resolution factor */ // int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2; /* ** Button Enumerations */ enum { BUTTON_CANCEL = 100, }; /* ** Dialog variables */ bool process = true; // process while true int retval; unsigned long starttime; int packetlen; int x,y,width,height; // dialog dimensions char buffer[80*3]; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); /* ** 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, SeenBuff.Get_Height(), width, height); width = max(width, 50 * RESFACTOR); width += 40 * RESFACTOR; height += 60 * RESFACTOR; x = (SeenBuff.Get_Width() - width) / 2; y = (SeenBuff.Get_Height() - height) / 2; TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1), y + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR); /* ** Initialize */ Set_Logic_Page(SeenBuff); process = true; /* ** Create the list */ commands = &cancelbtn; commands->Flag_List_To_Redraw(); /* ** Draw the dialog */ Hide_Mouse(); Load_Title_Page(true); Dialog_Box(x, y, width, height); Draw_Caption(TXT_NONE, x, y, width); Fancy_Text_Print(buffer, x + 20 * RESFACTOR, y + 25 * RESFACTOR, scheme, TBLACK, TPF_TEXT); commands->Draw_All(); while (Get_Mouse_State() > 0) Show_Mouse(); #ifdef WIN32 /* ** 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); #endif //WIN32 /* ** 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; while ( TickCount - starttime < 80) { NullModem.Service(); if ( NullModem.Get_Message( &ReceivePacket, &packetlen ) > 0) { if (ReceivePacket.Command == SERIAL_CONNECT) { starttime = TickCount; while (TickCount - 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.ScenarioInfo.Seed = TickCount; SendPacket.ID = (int) buffer; // address of buffer for more uniqueness. NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); starttime = TickCount; while (TickCount - starttime < 80) { NullModem.Service(); if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) { if (ReceivePacket.Command == SERIAL_CONNECT) { starttime = TickCount; while (TickCount - starttime < 30) NullModem.Service(); // // whoever has the highest time is the host // if (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) { process = false; retval = 2; } else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) { if (ReceivePacket.ID > SendPacket.ID) { process = false; retval = 2; // // if they are equal then it's a loopback cable or a modem // } else if (ReceivePacket.ID == SendPacket.ID) { process = false; retval = 3; } } break; } } } } starttime = TickCount; /* ** Main Processing Loop */ while (process) { #ifdef WIN32 /* ** 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(); } #endif //WIN32 /* ** Invoke game callback */ Call_Back(); /* ** Get user input */ KeyNumType input = commands->Input(); /* ** Process input */ switch (input) { case (KN_ESC): case (BUTTON_CANCEL | KN_BUTTON): retval = 0; process = false; break; default: break; } /* ** Service the connection. */ NullModem.Service(); if (NullModem.Num_Send() == 0) { if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) { if (ReceivePacket.Command == SERIAL_CONNECT) { starttime = TickCount; while (TickCount - starttime < 30) NullModem.Service(); // // whoever has the highest time is the host // if (ReceivePacket.ScenarioInfo.Seed > SendPacket.ScenarioInfo.Seed) { process = false; retval = 2; } else if (ReceivePacket.ScenarioInfo.Seed == SendPacket.ScenarioInfo.Seed) { if (ReceivePacket.ID > SendPacket.ID) { process = false; retval = 2; // // if they are equal then it's a loopback cable or a modem // } else if (ReceivePacket.ID == SendPacket.ID) { process = false; retval = 3; } } } else { retval = 0; process = false; } } else { retval = 1; process = false; } } if (TickCount - 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 (Session.ModemType) { 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) ) { status = Reconnect_Null_Modem(); } else { status = Dial_Modem( DialSettings, true ); } break; case (MODEM_ANSWERER): modemstatus = NullModem.Get_Modem_Status(); if ( (modemstatus & CD_SET) ) { 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; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 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, SeenBuff.Get_Height(), width, height); width = max(width, 50 * RESFACTOR); width += 40 * RESFACTOR; height += 60 * RESFACTOR; x = (SeenBuff.Get_Width() - width) / 2; y = (SeenBuff.Get_Height() - height) / 2; TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1), y + height - (FontHeight + FontYSpacing + 2*RESFACTOR) - 10 * RESFACTOR); /* ** 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*RESFACTOR, y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT); commands->Draw_All(); Show_Mouse(); /* ** Main Processing Loop */ starttime = lastmsgtime = TickCount; while (process) { #ifdef WIN32 /* ** 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(); } #endif //WIN32 /* ** 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 - starttime > PACKET_RETRANS_TIME) { starttime = TickCount; memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_CONNECT; SendPacket.ID = Session.ColorIdx; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0); } /* ** Check for an incoming message */ if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) { lastmsgtime = TickCount; if (ReceivePacket.Command == SERIAL_CONNECT) { // are we getting our own packets back?? if (ReceivePacket.ID == Session.ColorIdx) { WWMessageBox().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. */ memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_CONNECT; SendPacket.ID = Session.ColorIdx; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); starttime = TickCount; while (TickCount - starttime < 60) NullModem.Service(); retval = true; process = false; } } // // timeout if we do not get any packets // if (TickCount - 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; this should be the HousesType of the player being * * "destroyed". * * 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; HouseClass *housep; char txt[80]; if ( Session.NumPlayers == 1 ) { return; } /* ** Do nothing if the house isn't human. */ housep = HouseClass::As_Pointer((HousesType)id); if (!housep || !housep->IsHuman) return; /* ** Create a message to display to the user */ txt[0] = '\0'; switch (error) { case 1: sprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName); break; case 0: sprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName); break; case -1: NullModem.Delete_Connection(); break; } if (strlen(txt)) { Session.Messages.Add_Message (NULL, 0, txt, (housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE); Map.Flag_To_Redraw(false); } /* ** Remove this player from the Players vector */ for (i = 0; i < Session.Players.Count(); i++) { if (!stricmp(Session.Players[i]->Name,housep->IniName)) { delete Session.Players[i]; Session.Players.Delete(Session.Players[i]); break; } } /* ** Turn the player's house over to the computer's AI */ housep->IsHuman = false; // housep->Smartness = IQ_MENSA; housep->IQ = Rule.MaxIQ; strcpy (housep->IniName,Text_String(TXT_COMPUTER)); Session.NumPlayers--; /* ** If we're the last player left, tell the user. */ if (Session.NumPlayers == 1) { sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME)); Session.Messages.Add_Message (NULL, 0, txt, (housep->RemapColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE); Map.Flag_To_Redraw(false); } } /*************************************************************************** * 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; /* ** Dialog & button dimensions */ int d_dialog_w = 160 * RESFACTOR; // dialog width int d_dialog_h = 94 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = 80*RESFACTOR; // int d_dialog_y = ((136 * RESFACTOR - 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 = 7 * RESFACTOR; // ht of 6-pt text int d_margin = 7 * RESFACTOR; // margin width/height int d_dial_w = 90 * RESFACTOR; int d_dial_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_answer_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_nullmodem_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_settings_h = 9 * RESFACTOR; int d_settings_x = d_dialog_cx - d_settings_w / 2; int d_settings_y = d_nullmodem_y + d_nullmodem_h + 2; int d_cancel_w = 50 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; 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*RESFACTOR}; // 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; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); /* ** Buttons */ GadgetClass *commands; // button list TextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL_MODEM, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h); TextButtonClass answerbtn(BUTTON_ANSWER, TXT_ANSWER_MODEM, TPF_BUTTON, d_answer_x, d_answer_y, d_answer_w, d_answer_h); TextButtonClass nullmodembtn(BUTTON_NULLMODEM, TXT_NULL_MODEM, TPF_BUTTON, d_nullmodem_x, d_nullmodem_y, d_nullmodem_w, d_nullmodem_h); TextButtonClass settingsbtn(BUTTON_SETTINGS, TXT_SETTINGS, TPF_BUTTON, d_settings_x, d_settings_y, d_settings_w, d_settings_h); TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); /* ** Initialize */ Set_Logic_Page(SeenBuff); if (Session.SerialDefaults.Port == 0 || Session.SerialDefaults.IRQ == -1 || Session.SerialDefaults.Baud == -1) { selectsettings = true; } else if ( NullModem.Detect_Port( &Session.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, scheme, TBLACK, TPF_CENTER | TPF_TEXT); /* ** Main Processing Loop */ display = REDRAW_ALL; process = true; pressed = false; while (process) { /* ** Invoke game callback */ Call_Back(); /* ** Refresh display if needed */ #ifdef WIN32 /* ** 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; } #endif if (display) { Hide_Mouse(); if (display >= REDRAW_BACKGROUND) { /* ** Refresh the backdrop */ Load_Title_Page(true); /* ** Draw the background */ Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); /* ** Draw the labels */ Draw_Caption (TXT_SELECT_SERIAL_GAME, d_dialog_x, d_dialog_y, d_dialog_w); } commands->Draw_All(); 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) { WWMessageBox().Process(TXT_SELECT_SETTINGS); /* ** Remote-connect */ } else if ( Phone_Dialog() ) { if (Session.PhoneBook[Session.CurPhoneIdx]->Settings.Port == 0) { settings = &Session.SerialDefaults; } else { settings = &(Session.PhoneBook[Session.CurPhoneIdx]->Settings); } #ifdef WIN32 if (SerialPort) { delete SerialPort; } SerialPort = new WinModemClass; #endif //WIN32 if ( Init_Null_Modem( settings ) ) { if (settings->CallWaitStringIndex == CALL_WAIT_CUSTOM) { strcpy( DialString, settings->CallWaitString ); } else { strcpy( DialString, Session.CallWaitStrings[ settings->CallWaitStringIndex ] ); } strcat( DialString, Session.PhoneBook[ Session.CurPhoneIdx ]->Number ); if ( Dial_Modem( settings, false ) ) { Session.ModemType = MODEM_DIALER; if ( Com_Scenario_Dialog() ) { retval = GAME_MODEM; process = false; } } if (process) { // restore to default NullModem.Change_IRQ_Priority( 0 ); } } else { WWMessageBox().Process(TXT_SELECT_SETTINGS); } } if (process) { buttons[curbutton]->IsPressed = false; buttons[curbutton]->Flag_To_Redraw(); } display = REDRAW_ALL; break; case (BUTTON_ANSWER): if (selectsettings) { WWMessageBox().Process(TXT_SELECT_SETTINGS); } else { /* ** Remote-connect */ settings = &Session.SerialDefaults; #ifdef WIN32 if (SerialPort) { delete SerialPort; } SerialPort = new WinModemClass; #endif //WIN32 if ( Init_Null_Modem( settings ) ) { if ( Answer_Modem( settings, false ) ) { Session.ModemType = MODEM_ANSWERER; if ( Com_Show_Scenario_Dialog() ) { retval = GAME_MODEM; process = false; } } if (process) { // restore to default NullModem.Change_IRQ_Priority( 0 ); } } else { WWMessageBox().Process(TXT_SELECT_SETTINGS); } } if (process) { buttons[curbutton]->IsPressed = false; buttons[curbutton]->Flag_To_Redraw(); } display = REDRAW_ALL; break; case (BUTTON_NULLMODEM): if (selectsettings) { WWMessageBox().Process(TXT_SELECT_SETTINGS); /* ** Otherwise, remote-connect; save values if we're recording */ } else if ( Init_Null_Modem( &Session.SerialDefaults ) ) { rc = Test_Null_Modem(); switch (rc) { case (1): Session.ModemType = MODEM_NULL_HOST; if ( Com_Scenario_Dialog() ) { retval = GAME_NULL_MODEM; process = false; } break; case (2): Session.ModemType = MODEM_NULL_JOIN; if ( Com_Show_Scenario_Dialog() ) { retval = GAME_NULL_MODEM; process = false; } break; case (3): WWMessageBox().Process( TXT_MODEM_OR_LOOPBACK ); break; } if (process) { // restore to default NullModem.Change_IRQ_Priority( 0 ); } } else { WWMessageBox().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( &Session.SerialDefaults ) ) { Session.Write_MultiPlayer_Settings (); selectsettings = true; if (Session.SerialDefaults.Port != 0 && Session.SerialDefaults.IRQ != -1 && Session.SerialDefaults.Baud != -1) { if ( NullModem.Detect_Port( &Session.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 */ return( retval ); } #ifdef WIN32 /*********************************************************************************************** * Advanced_Modem_Settings -- Allows to user to set additional modem settings * * * * * * * * INPUT: current settings * * * * OUTPUT: modified settings * * * * WARNINGS: None * * * * HISTORY: * * 12/16/96 2:29PM ST : Created * *=============================================================================================*/ Advanced_Modem_Settings (SerialSettingsType *settings) { /*........................................................................ Dialog & button dimensions ........................................................................*/ #if (FRENCH | GERMAN) int d_dialog_w = 440; // dialog width #else int d_dialog_w = 340; // dialog width #endif int d_dialog_h = 200; // dialog height int d_dialog_x = 320 - d_dialog_w/2; // dialog x-coord int d_dialog_y = 200 - d_dialog_h/ 4; // dialog y-coord int d_compression_w = 50; int d_compression_h = 18; int d_compression_x = d_dialog_x + d_dialog_w/2 +40; int d_compression_y = d_dialog_y + 40; int d_errorcorrection_w = 50; int d_errorcorrection_h = 18; int d_errorcorrection_x = d_dialog_x + d_dialog_w/2 +40; int d_errorcorrection_y = d_dialog_y + 65; int d_hardwareflowcontrol_w = 50; int d_hardwareflowcontrol_h = 18; int d_hardwareflowcontrol_x = d_dialog_x + d_dialog_w/2 +40; int d_hardwareflowcontrol_y = d_dialog_y + 90; int d_default_w = 100; int d_default_h = 18; int d_default_x = d_dialog_x + d_dialog_w / 2 - d_default_w / 2; int d_default_y = d_dialog_y + d_dialog_h - 70; int d_ok_w = 100; int d_ok_h = 18; int d_ok_x = d_dialog_x + d_dialog_w/2 - d_ok_w / 2; int d_ok_y = d_dialog_y + d_dialog_h - 40; enum { BUTTON_COMPRESSION = 100, BUTTON_ERROR_CORRECTION, BUTTON_HARDWARE_FLOW_CONTROL, BUTTON_DEFAULT, BUTTON_OK, }; typedef enum { REDRAW_NONE = 0, REDRAW_BUTTONS, REDRAW_BACKGROUND, REDRAW_ALL = REDRAW_BACKGROUND, } RedrawType; /* ** Yes/No strings */ char compress_text [16]; char correction_text [16]; char flowcontrol_text[16]; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); /* ** Initialise the button text */ strcpy (compress_text, settings->Compression ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); strcpy (correction_text, settings->ErrorCorrection ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); strcpy (flowcontrol_text, settings->HardwareFlowControl ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); /* ** Create the buttons */ TextButtonClass compressionbutton(BUTTON_COMPRESSION, compress_text, TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW, d_compression_x, d_compression_y, d_compression_w, d_compression_h); TextButtonClass errorcorrectionbutton(BUTTON_ERROR_CORRECTION, correction_text, TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW, d_errorcorrection_x, d_errorcorrection_y, d_errorcorrection_w, d_errorcorrection_h); TextButtonClass hardwareflowcontrolbutton(BUTTON_HARDWARE_FLOW_CONTROL, flowcontrol_text, TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW, d_hardwareflowcontrol_x, d_hardwareflowcontrol_y, d_hardwareflowcontrol_w, d_hardwareflowcontrol_h); TextButtonClass defaultbutton(BUTTON_DEFAULT, TXT_DEFAULT, TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW, d_default_x, d_default_y, d_default_w, d_default_h); TextButtonClass okbutton(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); /* ** Misc. variables. */ RedrawType display = REDRAW_ALL; // redraw level BOOL process = true; // process while true KeyNumType input; GadgetClass *commands; // button list commands = &okbutton; defaultbutton.Add_Tail(*commands); compressionbutton.Add_Tail(*commands); errorcorrectionbutton.Add_Tail(*commands); hardwareflowcontrolbutton.Add_Tail(*commands); /* ** Main process 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_Page(true); CCPalette.Set(); Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); // init font variables Fancy_Text_Print(TXT_NONE, 0, 0, scheme, TBLACK, TPF_TEXT); /*............................................................... Dialog & Field labels ...............................................................*/ Draw_Caption (TXT_MODEM_INITIALISATION, d_dialog_x, d_dialog_y, d_dialog_w); Fancy_Text_Print( TXT_DATA_COMPRESSION, d_compression_x - 26, d_compression_y + 2, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print( TXT_ERROR_CORRECTION, d_errorcorrection_x - 26, d_errorcorrection_y +2, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print( TXT_HARDWARE_FLOW_CONTROL, d_hardwareflowcontrol_x -26, d_hardwareflowcontrol_y +2, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); } /* .......................... Redraw buttons .......................... */ if (display >= REDRAW_BUTTONS) { compressionbutton.Flag_To_Redraw(); errorcorrectionbutton.Flag_To_Redraw(); hardwareflowcontrolbutton.Flag_To_Redraw(); } Show_Mouse(); display = REDRAW_NONE; } /* ........................... Get user input ............................ */ input = commands->Input(); /* ---------------------------- Process input ---------------------------- */ switch (input) { case (BUTTON_COMPRESSION | KN_BUTTON): settings->Compression = settings->Compression ^ 1; strcpy (compress_text, settings->Compression ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); if (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS; break; case (BUTTON_ERROR_CORRECTION | KN_BUTTON): settings->ErrorCorrection = settings->ErrorCorrection ^ 1; strcpy (correction_text, settings->ErrorCorrection ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); if (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS; break; case (BUTTON_HARDWARE_FLOW_CONTROL | KN_BUTTON): settings->HardwareFlowControl = settings->HardwareFlowControl ^ 1; strcpy (flowcontrol_text, settings->HardwareFlowControl ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); if (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS; break; case (BUTTON_DEFAULT | KN_BUTTON): settings->Compression = false; settings->ErrorCorrection = false; settings->HardwareFlowControl = true; strcpy (compress_text, settings->Compression ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); strcpy (correction_text, settings->ErrorCorrection ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); strcpy (flowcontrol_text, settings->HardwareFlowControl ? Text_String (TXT_ON) : Text_String (TXT_OFF) ); if (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS; break; case (BUTTON_OK | KN_BUTTON): process = false; break; } } } #endif //WIN32 /*************************************************************************** * Com_Settings_Dialog -- Lets user select serial port settings * * * * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ * * ³ Settings ³ * * ³ ³ * * ³ Port:____ IRQ:__ Baud:______ ³ * * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * * ³ ³ ³ ³ ³ ³ ³ ³ * * ³ ³ ³ ³ ³ ³ ³ ³ * * ³ ³ ³ ³ ³ ³ ³ ³ * * ³ ³ ³ ³ ³ ³ ³ ³ * * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * * ³ ³ * * ³ Initialization: [Add] [Delete] ³ * * ³ _____________________________ ³ * * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * * ³ ³ ³ ³ * * ³ ³ ³ ³ * * ³ ³ ³ ³ * * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * * ³ ³ * * ³ Call Waiting: ³ * * ³ _______________ ³ * * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ [Tone Dialing] ³ * * ³ ³ ³ ³ * * ³ ³ ³ [Pulse Dialing] ³ * * ³ ³ ³ ³ * * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * * ³ ³ * * ³ [OK] [Cancel] ³ * * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ * * * * 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 ) { /* ** Dialog & button dimensions */ int d_dialog_w = 320 * RESFACTOR; // dialog width int d_dialog_h = 200 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = ((200 * RESFACTOR - 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 = 7 * RESFACTOR; // ht of 6-pt text int d_margin = 5 * RESFACTOR; // margin width/height int d_portlist_w = 80 * RESFACTOR + 80*(RESFACTOR-1); //Port list wider in hires int d_portlist_h = 33 * RESFACTOR; int d_portlist_x = d_dialog_x + (d_dialog_w / 6) - (d_portlist_w / 2); #ifdef WIN32 d_portlist_x = 0x45; #endif int d_portlist_y = d_dialog_y + ((d_margin + d_txt6_h) * 2) + d_margin + 10 * RESFACTOR; #ifdef WIN32 int d_port_w = d_portlist_w; int d_port_x = 0x45; #else int d_port_w = (5 * 6 * RESFACTOR) + 3 * RESFACTOR; // int d_port_x = d_portlist_x + 29 * RESFACTOR; #ifdef FRENCH //VG2 int d_port_x = (d_portlist_x + 29 * RESFACTOR) + 5; #else int d_port_x = d_portlist_x + 29 * RESFACTOR; #endif #endif //WIN32 int d_port_h = 9 * RESFACTOR; int d_port_y = d_portlist_y - d_margin - d_txt6_h; int d_irqlist_w = 80 * RESFACTOR; int d_irqlist_h = 33 * RESFACTOR; 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 * RESFACTOR) + 3 * RESFACTOR; int d_irq_h = 9 * RESFACTOR; int d_irq_x = d_irqlist_x + 25 * RESFACTOR; int d_irq_y = d_irqlist_y - d_margin - d_txt6_h; int d_baudlist_w = 80 * RESFACTOR; int d_baudlist_h = 33 * RESFACTOR; int d_baudlist_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_baudlist_w / 2); #ifdef WIN32 d_baudlist_x -= 32; #endif int d_baudlist_y = d_irqlist_y; int d_baud_w = ((BAUDBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR; int d_baud_h = 9 * RESFACTOR; int d_baud_x = d_baudlist_x + 29 * RESFACTOR; int d_baud_y = d_baudlist_y - d_margin - d_txt6_h; int d_initstrlist_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 8 * RESFACTOR + 3 * RESFACTOR; int d_initstrlist_h = 21 * RESFACTOR; int d_initstrlist_x = d_dialog_cx - (d_initstrlist_w / 2); int d_initstrlist_y = d_portlist_y + d_portlist_h + ((d_margin + d_txt6_h) * 2) + d_margin + 4; int d_initstr_w = ((INITSTRBUF_MAX - 1) * 6 * RESFACTOR) + 3 * RESFACTOR; int d_initstr_h = 9 * RESFACTOR; int d_initstr_x = d_initstrlist_x; int d_initstr_y = d_initstrlist_y - d_margin - d_txt6_h; int d_add_w = 45 * RESFACTOR; #ifdef FRENCH int d_add_x = d_dialog_cx - (d_add_w / 2); #else int d_add_x = (d_dialog_cx - (d_add_w / 2)) + 30; #endif int d_add_h = 9 * RESFACTOR; int d_add_y = d_initstr_y - d_add_h - 3 * RESFACTOR; int d_delete_w = 45 * RESFACTOR; #ifdef FRENCH int d_delete_x = (d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2)) + 10; #else int d_delete_x = d_dialog_x + ((d_dialog_w * 3) / 4) - (d_delete_w / 2); #endif int d_delete_h = 9 * RESFACTOR; int d_delete_y = d_initstr_y - d_add_h - 3 * RESFACTOR; int d_cwaitstrlist_w = (((CWAITSTRBUF_MAX - 1) + 9) * 6) * RESFACTOR + 3 * RESFACTOR; int d_cwaitstrlist_h = 27 * RESFACTOR; int d_cwaitstrlist_x = d_initstrlist_x; int d_cwaitstrlist_y = d_initstrlist_y + d_initstrlist_h + ((d_margin + d_txt6_h) * 2) + 2; int d_cwaitstr_w = ((CWAITSTRBUF_MAX - 1) * 6) * RESFACTOR + 3 * RESFACTOR; int d_cwaitstr_h = 9 * RESFACTOR; int d_cwaitstr_x = d_cwaitstrlist_x; int d_cwaitstr_y = d_cwaitstrlist_y - d_margin - d_txt6_h; int d_tone_w = 80 * RESFACTOR; int d_tone_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_pulse_h = 9 * RESFACTOR; 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; #ifdef FRENCH int d_save_w = 80 * RESFACTOR; #else int d_save_w = 40 * RESFACTOR; #endif int d_save_h = 9 * RESFACTOR; int d_save_x = d_dialog_x + (d_dialog_w / 5) - (d_save_w / 2); int d_save_y = d_dialog_y + d_dialog_h - d_save_h - d_margin - 4*RESFACTOR; int d_cancel_w = 50 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; int d_cancel_x = d_dialog_x + ((d_dialog_w * 4) / 5) - (d_cancel_w / 2); int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin - 4*RESFACTOR; #if (GERMAN | FRENCH) int d_advanced_w = 50*RESFACTOR; #else int d_advanced_w = 40*RESFACTOR; #endif int d_advanced_h = 9*RESFACTOR; int d_advanced_x = d_dialog_x + ((d_dialog_w) / 2) - (d_advanced_w / 2); int d_advanced_y = d_dialog_y + d_dialog_h - d_advanced_h - d_margin - 4 *RESFACTOR; /* ** 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_ADVANCED, 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[4] = { "COM1 - 3F8", "COM2 - 2F8", "COM3 - 3E8", "COM4 - 2E8", }; static char custom_port[10 + MODEM_NAME_MAX] = {"CUSTOM - ????"}; #ifndef WIN32 // No IRQ dialog in Win version static char *irqname[5] = { "2 / 9", "3 - [COM2 & 4]", "4 - [COM1 & 3]", "5", "CUSTOM - ??" }; static int _irqidx[4] = { 2, 1, 2, 1 }; #endif //WIN32 #ifdef WIN32 static char *baudname[5] = { "14400", "19200", "28800", "38400", "57600", }; static char modemnames[10][MODEM_NAME_MAX]; #else //WIN32 static char *baudname[5] = { "9600", "14400", "19200", "28800", "38400" }; #endif //WIN32 /* ** 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 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); char portbuf[ PORTBUF_MAX ] = {0}; // buffer for port char irqbuf[ IRQBUF_MAX ] = {0}; // buffer for 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) int port_custom_index = 4; //index of custom entry in port list int irq_index = 1; // index of currently-selected irq (default = 3) 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; bool firsttime = true; SerialSettingsType tempsettings; DetectPortType dpstatus; /* ** Buttons */ GadgetClass *commands; // button list EditClass port_edt (BUTTON_PORT, portbuf, PORTBUF_MAX, TPF_TEXT, 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_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); #ifndef WIN32 EditClass irq_edt (BUTTON_IRQ, irqbuf, IRQBUF_MAX, TPF_TEXT, 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_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); #endif //WIN32 EditClass baud_edt (BUTTON_BAUD, baudbuf, BAUDBUF_MAX, TPF_TEXT, 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_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); EditClass initstr_edt (BUTTON_INITSTR, initstrbuf, INITSTRBUF_MAX, TPF_TEXT, 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_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); TextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h); TextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h); EditClass cwaitstr_edt (BUTTON_CWAITSTR, cwaitstrbuf, CWAITSTRBUF_MAX, TPF_TEXT, 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_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); TextButtonClass tonebtn(BUTTON_TONE, TXT_TONE_BUTTON, TPF_BUTTON, d_tone_x, d_tone_y, d_tone_w, d_tone_h); TextButtonClass pulsebtn(BUTTON_PULSE, TXT_PULSE_BUTTON, TPF_BUTTON, d_pulse_x, d_pulse_y, d_pulse_w, d_pulse_h); TextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h); TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); #ifdef WIN32 TextButtonClass advancedbutton(BUTTON_ADVANCED, TXT_ADVANCED, TPF_BUTTON, d_advanced_x, d_advanced_y, d_advanced_w, d_advanced_h); #endif //WIN32 /* ** Various Inits */ memcpy( &tempsettings, settings, sizeof(SerialSettingsType) ); if (tempsettings.Port == 0) { tempsettings.Port = 0x2f8; } if (tempsettings.IRQ == -1) { tempsettings.IRQ = 3; } if (tempsettings.Baud == -1) { #ifdef WIN32 tempsettings.Baud = 19200; #else //WIN32 tempsettings.Baud = 9600; #endif //WIN32 } /* ** Set the current indices */ #ifndef WIN32 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 //WIN32 #ifdef WIN32 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; } #else //WIN32 if (tempsettings.Baud == 9600) { baud_index = 0; } else if (tempsettings.Baud == 14400) { baud_index = 1; } else if (tempsettings.Baud == 19200) { baud_index = 2; } else if (tempsettings.Baud == 28800) { baud_index = 3; } else { baud_index = 4; } #endif //WIN32 sprintf (baudbuf, "%d", tempsettings.Baud); /* ** Set up the port list box & edit box */ for (i = 0; i < 4; i++) { portlist.Add_Item( portname[ i ] ); } #ifdef WIN32 /* ** Loop through the first 10 possible modem entries in the registry. Frankly, its just ** tough luck if the user has more than 10 modems attached! */ if (ModemRegistry) { delete ModemRegistry; } int modems_found = 0; for (i=0 ; i<10 ; i++) { ModemRegistry = new ModemRegistryEntryClass (i); if (ModemRegistry->Get_Modem_Name()) { strncpy (modemnames[modems_found], ModemRegistry->Get_Modem_Name(), MODEM_NAME_MAX); portlist.Add_Item( modemnames [modems_found++] ); port_custom_index ++; } delete ModemRegistry; } ModemRegistry = NULL; #endif //WIN32 portlist.Add_Item ( custom_port ); /* ** Work out the current port index */ port_index = -1; #ifdef WIN32 if (tempsettings.ModemName[0]) { for ( i=0 ; i= REDRAW_BACKGROUND) { Load_Title_Page(true); CCPalette.Set(); 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_TEXT); /* ** 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 * RESFACTOR, d_port_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT); #ifndef WIN32 Fancy_Text_Print(TXT_IRQ_COLON, d_irq_x - 3 * RESFACTOR, d_irq_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT); #endif //WIN32 Fancy_Text_Print(TXT_BAUD_COLON, d_baud_x - 3 * RESFACTOR, d_baud_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT); Fancy_Text_Print(TXT_INIT_STRING, d_initstr_x, d_initstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT); Fancy_Text_Print(TXT_CWAIT_STRING, d_cwaitstr_x, d_cwaitstr_y - d_txt6_h - 3 * RESFACTOR, scheme, TBLACK, TPF_TEXT); } /* ** Redraw buttons */ if (display >= REDRAW_BUTTONS) { cancelbtn.Flag_To_Redraw(); port_edt.Flag_To_Redraw(); portlist.Flag_To_Redraw(); #ifndef WIN32 irq_edt.Flag_To_Redraw(); irqlist.Flag_To_Redraw(); #endif //WIN32 baud_edt.Flag_To_Redraw(); baudlist.Flag_To_Redraw(); #ifdef WIN32 advancedbutton.Flag_To_Redraw(); #endif //WIN32 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 = false; } /* ** Process input */ switch (input) { #ifdef WIN32 case (BUTTON_ADVANCED | KN_BUTTON): Advanced_Modem_Settings (&tempsettings); display = REDRAW_ALL; break; #endif //WIN32 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(); #ifndef WIN32 irq_edt.Set_Focus(); irq_edt.Flag_To_Redraw(); #endif //WIN32 } 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: #ifdef WIN32 if (portbuf[3] <= '9' && portbuf[3] >'0') { portbuf[4] = 0; port_index = port_custom_index; 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; } break; } #endif //WIN32 WWMessageBox().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; } } #ifndef WIN32 if (display == REDRAW_BUTTONS) { irq_edt.Set_Focus(); irq_edt.Flag_To_Redraw(); } #endif //WIN32 } 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, ' ' ); pos = (int)(temp - item); strncpy( portbuf, item, pos ); portbuf[pos] = 0; port_edt.Clear_Focus(); // auto select the irq for port #ifndef WIN32 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 //WIN32 } else { if (port_index == port_custom_index) { /* ** This is the custom entry */ 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(); } else { /* ** Must be a modem name entry so just copy iy */ strncpy (portbuf, item, PORTBUF_MAX); } } port_edt.Set_Text( portbuf, PORTBUF_MAX ); } else if (port_index < port_custom_index) { port_edt.Clear_Focus(); } else { port_edt.Set_Focus(); } display = REDRAW_BUTTONS; break; #ifndef WIN32 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 //WIN32 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( Session.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 ); Session.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 < Session.InitStrings.Count(); i++) { if (item == Session.InitStrings[i]) { initstr_index = i; strcpy( initstrbuf, Session.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 ( Session.InitStrings.Count() && initstr_index != -1) { Session.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; tempsettings.ModemName[0] = 0; break; case ( 1 ): tempsettings.Port = 0x2f8; tempsettings.ModemName[0] = 0; break; case ( 2 ): tempsettings.Port = 0x3e8; tempsettings.ModemName[0] = 0; break; case ( 3 ): tempsettings.Port = 0x2e8; tempsettings.ModemName[0] = 0; break; default: if (port_index == port_custom_index) { #ifdef WIN32 strncpy ( tempsettings.ModemName, portbuf, MODEM_NAME_MAX ); tempsettings.Port = 1; #else //WIN32 sscanf( portbuf, "%x", &tempsettings.Port ); tempsettings.ModemName[0] = 0; #endif //WIN32 } else { /* ** Must be a modem name index */ strcpy (tempsettings.ModemName, portlist.Current_Item()); tempsettings.Port = 1; } break; } #ifndef WIN32 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 //WIN32 sscanf( baudbuf, "%d", &tempsettings.Baud ); tempsettings.InitStringIndex = initstr_index; tempsettings.CallWaitStringIndex = cwaitstr_index; item = Session.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) { #ifdef WIN32 WWMessageBox().Process( TXT_UNABLE_TO_OPEN_PORT ); #else //WIN32 WWMessageBox().Process( TXT_INVALID_SETTINGS ); #endif //WIN32 firsttime = true; display = REDRAW_ALL; } else if (dpstatus == PORT_IRQ_INUSE) { WWMessageBox().Process( TXT_IRQ_ALREADY_IN_USE ); firsttime = true; 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_Page(true); 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 *)(&Session.InitStrings[0]), Session.InitStrings.Count(), sizeof(char *), Init_String_Compare); /*........................................................................ Build the list ........................................................................*/ for (i = 0; i < Session.InitStrings.Count(); i++) { item = new char[ INITSTRBUF_MAX ]; strcpy( item, Session.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, Session.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 * * * * * * INPUT: * * none. * * * * OUTPUT: * * true = success, false = cancel * * * * WARNINGS: * * none. * * * * HISTORY: * * 02/14/1995 BR : Created. * 01/21/97 V.Grippi added check for CS before sending scenario file * *=============================================================================================*/ int Com_Scenario_Dialog(bool skirmish) { /*........................................................................ Dialog & button dimensions ........................................................................*/ int d_dialog_w = 320 * RESFACTOR; // dialog width int d_dialog_h = 200 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = ((200 * RESFACTOR - 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 * RESFACTOR+1; // ht of 6-pt text int d_margin1 = 5 * RESFACTOR; // margin width/height int d_margin2 = 7 * RESFACTOR; // margin width/height int d_name_w = 70 * RESFACTOR; int d_name_h = 9 * RESFACTOR; int d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2); int d_name_y = d_dialog_y + d_margin2 + d_txt6_h + 1 * RESFACTOR; #ifdef OLDWAY int d_gdi_w = 40 * RESFACTOR; int d_gdi_h = 9 * RESFACTOR; int d_gdi_x = d_dialog_cx - d_gdi_w; int d_gdi_y = d_name_y; int d_nod_w = 40 * RESFACTOR; int d_nod_h = 9 * RESFACTOR; int d_nod_x = d_dialog_cx; int d_nod_y = d_name_y; #else int d_house_w = 60 *RESFACTOR; int d_house_h = (8 * 5 *RESFACTOR); int d_house_x = d_dialog_cx - (d_house_w / 2); int d_house_y = d_name_y; #endif int d_color_w = 10 * RESFACTOR; int d_color_h = 9 * RESFACTOR; int d_color_y = d_name_y; int d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3); int d_playerlist_w = 118 * RESFACTOR; int d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR; // 6 rows high int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR; int d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h*/; int d_scenariolist_w = 162 * RESFACTOR; int d_scenariolist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR; // 6 rows high if (skirmish) { d_scenariolist_h *= 2; } int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - 5*RESFACTOR; int d_scenariolist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR; if (skirmish) { d_scenariolist_x = d_dialog_x + (d_dialog_w-d_scenariolist_w)/2; } int d_count_w = 25 * RESFACTOR; int d_count_h = d_txt6_h; int d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR; // (fudged) int d_count_y = d_playerlist_y + d_playerlist_h + (d_margin1 * 2) - 2 * RESFACTOR; if (skirmish) { d_count_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR; } int d_level_w = 25 * RESFACTOR; int d_level_h = d_txt6_h; int d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR; // (fudged) int d_level_y = d_count_y + d_count_h; int d_credits_w = 25 * RESFACTOR; int d_credits_h = d_txt6_h; int d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20 * RESFACTOR; // (fudged) int d_credits_y = d_level_y + d_level_h; int d_aiplayers_w = 25*RESFACTOR; int d_aiplayers_h = d_txt6_h; int d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged) int d_aiplayers_y = d_credits_y + d_credits_h; int d_options_w = 106 * RESFACTOR; int d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR; int d_options_x = d_dialog_x + d_dialog_w - 149 * RESFACTOR; int d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1 - 2*RESFACTOR; int d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR; int d_message_h = (8 * d_txt6_h) + 3 * RESFACTOR; // 4 rows high int d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR; int d_message_y = d_options_y + d_options_h + 2*RESFACTOR; int d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR; int d_send_h = 9 * RESFACTOR; int d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR; int d_send_y = d_message_y + d_message_h; int d_ok_w = 45 * RESFACTOR; int d_ok_h = 9 * RESFACTOR; int d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2); int d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - RESFACTOR*6; int d_cancel_w = 45 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; int d_cancel_x = d_dialog_cx - (d_cancel_w / 2); int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - RESFACTOR*6; int d_load_w = 45 * RESFACTOR; int d_load_h = 9 * RESFACTOR; int d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2); int d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - RESFACTOR*6; /*........................................................................ Button Enumerations ........................................................................*/ enum { BUTTON_NAME = 100, #ifdef OLDWAY BUTTON_GDI, BUTTON_NOD, #else BUTTON_HOUSE, #endif BUTTON_CREDITS, BUTTON_AIPLAYERS, BUTTON_OPTIONS, BUTTON_PLAYERLIST, BUTTON_SCENARIOLIST, BUTTON_COUNT, BUTTON_LEVEL, BUTTON_OK, BUTTON_LOAD, BUTTON_CANCEL, BUTTON_DIFFICULTY, }; /*........................................................................ Redraw values: in order from "top" to "bottom" layer of the dialog ........................................................................*/ typedef enum { REDRAW_NONE = 0, REDRAW_PARMS, 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; int playertabs[] = {77*RESFACTOR}; // tabs for player list box int optiontabs[] = {8}; // tabs for player list box char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name bool transmit; // 1 = re-transmit new game options int cbox_x[] = { d_color_x, d_color_x + d_color_w, d_color_x + (d_color_w * 2), d_color_x + (d_color_w * 3), d_color_x + (d_color_w * 4), d_color_x + (d_color_w * 5), d_color_x + (d_color_w * 6), d_color_x + (d_color_w * 7) }; bool parms_received = false; // 1 = game options received bool changed = false; // 1 = user has changed an option int rc; int recsignedoff = false; int i; unsigned long version; unsigned long starttime; unsigned long timingtime; unsigned long lastmsgtime; unsigned long lastredrawtime; unsigned long transmittime = 0; unsigned long theirresponsetime; int packetlen; static bool first_time = true; bool oppscorescreen = false; bool gameoptions = Session.Type == GAME_SKIRMISH; EventClass *event; // event ptr unsigned long msg_timeout = 1200; // init to 20 seconds CCFileClass loadfile ("SAVEGAME.NET"); bool load_game = false; // 1 = load a saved game NodeNameType *who; // node to add to Players char *item; // for filling in lists RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); bool messages_have_focus = true; // Gadget focus starts on the message system Set_Logic_Page(SeenBuff); CDTimerClass kludge_timer; // Timer to allow a wait after client joins // game before game can start bool ok_button_added = false; /*........................................................................ Buttons ........................................................................*/ GadgetClass * commands; // button list EditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC); #ifdef OLDWAY TextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h); TextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h); #else char housetext[25] = ""; Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT); DropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext), TPF_TEXT, d_house_x, d_house_y, d_house_w, d_house_h, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); #endif ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); ListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h); char staticcountbuff[35]; StaticButtonClass staticcount(0, " ", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y); GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h); char staticlevelbuff[35]; StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y); GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h); char staticcreditsbuff[35]; StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y); GaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h); char staticaibuff[35]; StaticButtonClass staticai(0, " ", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y); CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); TextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w, d_ok_h); TextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, d_load_w, d_load_h); TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); SliderClass difficulty(BUTTON_DIFFICULTY, d_name_x, optionlist.Y + optionlist.Height + d_margin1 + d_margin1, d_dialog_w - (d_name_x-d_dialog_x)*2, 8*RESFACTOR, true); if (Rule.IsFineDifficulty) { difficulty.Set_Maximum(5); difficulty.Set_Value(2); } else { difficulty.Set_Maximum(3); difficulty.Set_Value(1); } /* ------------------------- Build the button list -------------------------- */ commands = &name_edt; staticcount.Add_Tail(*commands); staticcredits.Add_Tail(*commands); staticai.Add_Tail(*commands); staticlevel.Add_Tail(*commands); if (!skirmish) { playerlist.Add_Tail(*commands); } else { difficulty.Add_Tail(*commands); } scenariolist.Add_Tail(*commands); countgauge.Add_Tail(*commands); levelgauge.Add_Tail(*commands); creditsgauge.Add_Tail(*commands); aiplayersgauge.Add_Tail(*commands); optionlist.Add_Tail(*commands); if (Session.Type == GAME_SKIRMISH){ okbtn.Add_Tail(*commands); } cancelbtn.Add_Tail(*commands); if (!skirmish && loadfile.Is_Available()) { #ifdef FIXIT_MULTI_SAVE //Load button added only when other player has arrived //loadbtn.Add_Tail(*commands); #endif } else { cancelbtn.X = loadbtn.X; } #ifdef OLDWAY gdibtn.Add_Tail(*commands); nodbtn.Add_Tail(*commands); #else housebtn.Add_Tail(*commands); #endif /* ----------------------------- Various Inits ------------------------------ */ /*........................................................................ Init player name & house ........................................................................*/ Session.ColorIdx = Session.PrefColor; // init my preferred color strcpy (namebuf, Session.Handle); // set my name name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX); name_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { gdibtn.Turn_On(); } else { nodbtn.Turn_On(); } #else for (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) { housebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name())); } housebtn.Set_Selected_Index(Session.House - HOUSE_USSR); housebtn.Set_Read_Only (true); #endif /*........................................................................ Init scenario values, only the first time through ........................................................................*/ Special.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag; if (first_time) { Session.Options.Credits = Rule.MPDefaultMoney; // init credits & credit buffer Session.Options.Bases = Rule.IsMPBasesOn; // init scenario parameters Session.Options.Tiberium = Rule.IsMPTiberiumGrow; Session.Options.Goodies = Rule.IsMPCrates; Session.Options.AIPlayers = 0; Special.IsShadowGrow = Rule.IsMPShadowGrow; Session.Options.UnitCount = (SessionClass::CountMax[Session.Options.Bases] + SessionClass::CountMin[Session.Options.Bases]) / 2; first_time = false; } /*........................................................................ Init button states ........................................................................*/ playerlist.Set_Tabs(playertabs); playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL); optionlist.Set_Tabs(optiontabs); optionlist.Set_Read_Only(0); optionlist.Add_Item(Text_String(TXT_BASES)); optionlist.Add_Item(Text_String(TXT_ORE_SPREADS)); optionlist.Add_Item(Text_String(TXT_CRATES)); optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS)); if (!skirmish) { optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG)); } optionlist.Check_Item(0, Session.Options.Bases); optionlist.Check_Item(1, Session.Options.Tiberium); optionlist.Check_Item(2, Session.Options.Goodies); optionlist.Check_Item(3, Special.IsShadowGrow); if (!skirmish) { optionlist.Check_Item(4, Special.IsCaptureTheFlag); } countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1); levelgauge.Set_Value(BuildLevel - 1); creditsgauge.Set_Maximum(Rule.MPMaxMoney); creditsgauge.Set_Value(Session.Options.Credits); int maxp = Rule.MaxPlayers - 2; // int maxp = Rule.MaxPlayers - (skirmish ? 1 : 2); aiplayersgauge.Set_Maximum(maxp); if (skirmish) { if ( Session.Options.AIPlayers > 7 ) { Session.Options.AIPlayers = 7; } Session.Options.AIPlayers = max(Session.Options.AIPlayers, 1); }else{ if ( Session.Options.AIPlayers > 6 ) { Session.Options.AIPlayers = 6; } } aiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0)); /*........................................................................ Init other scenario parameters ........................................................................*/ Special.IsTGrowth = //Session.Options.Tiberium; Rule.IsTGrowth = //Session.Options.Tiberium; Special.IsTSpread = //Session.Options.Tiberium; Rule.IsTSpread = Session.Options.Tiberium; transmit = true; /*........................................................................ Clear the Players vector ........................................................................*/ Clear_Vector(&Session.Players); /*........................................................................ Init scenario description list box ........................................................................*/ for (i = 0; i < Session.Scenarios.Count(); i++) { for (int j = 0; EngMisStr[j] != NULL; j++) { if (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) { #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed). // Add mission if it's available to us. if( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) || ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) ) #endif #if defined(GERMAN) || defined(FRENCH) scenariolist.Add_Item(EngMisStr[j+1]); #else scenariolist.Add_Item(EngMisStr[j]); #endif break; } } if (EngMisStr[j] == NULL) { #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed). Added officialness check. // Add mission if it's available to us. if( !Session.Scenarios[i]->Get_Official() || !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) || ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) ) #endif scenariolist.Add_Item(Session.Scenarios[i]->Description()); } } Session.Options.ScenarioIndex = 0; // 1st scenario is selected /*........................................................................ Init random-number generator, & create a seed to be used for all random numbers from here on out ........................................................................*/ #ifdef FIXIT_RANDOM_GAME srand(time(NULL)); Seed = rand(); #else // randomize(); // Seed = rand(); #endif /*........................................................................ Init the message display system ........................................................................*/ if (!skirmish) { Session.Messages.Init (d_message_x + 1, d_message_y + 1, 8, MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1, d_send_y + 1, 1, 20, MAX_MESSAGE_LENGTH - 5, d_message_w); Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, NULL, '_', d_message_w); } /*........................................................................ Init version number clipping system ........................................................................*/ VerNum.Init_Clipping(); Load_Title_Page(true); CCPalette.Set(); extern char ModemRXString[]; if (strlen(ModemRXString) > 36) ModemRXString[36] = 0; if (strlen(ModemRXString) > 0) Session.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN, TPF_TEXT, -1); ModemRXString[0] = '\0'; /* ---------------------------- Init Mono Output ---------------------------- */ #if(SHOW_MONO) if (!skirmish) { NullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType), SerialPacketNames, 100, 8); NullModem.Mono_Debug_Print(1); } #endif /* ---------------------------- Processing loop ----------------------------- */ if (!skirmish) { NullModem.Reset_Response_Time(); // clear response time } theirresponsetime = 10000; // initialize to an invalid value timingtime = lastmsgtime = lastredrawtime = TickCount; /* ** Those easily offended should avert their eyes from the following line. And whatever ** you do, dont search for 'goto'. */ oh_dear_its_a_label: while (process) { #if(SHOW_MONO) if (!skirmish) { NullModem.Mono_Debug_Print(0); } #endif if (!skirmish){ if (!ok_button_added && gameoptions && kludge_timer == 0){ okbtn.Add_Tail(*commands); ok_button_added = true; #ifdef FIXIT_VERSION_3 if( loadfile.Is_Available() ) { loadbtn.Add_Tail( *commands ); } #else #ifdef FIXIT_MULTI_SAVE if ( loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) { loadbtn.Add_Tail ( *commands ); } #endif #endif if (display < REDRAW_BUTTONS) display = REDRAW_BUTTONS; } } /* ** Kludge to make sure we redraw the message input line when it loses focus. ** If we dont do this then the cursor doesnt disappear. */ if (!skirmish) { if (messages_have_focus) { if (name_edt.Has_Focus()) { if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; messages_have_focus = false; } } else { if (!name_edt.Has_Focus()) { messages_have_focus = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; Session.Messages.Set_Edit_Focus(); } } } /* ........................ Invoke game callback ......................... */ Call_Back(); #ifdef WIN32 /* ** 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; } #endif /* ...................... Refresh display if needed ...................... */ if (display) { if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } 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_TEXT); /*............................................................... Dialog & Field labels ...............................................................*/ Fancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #ifdef OLDWAY Fancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #else Fancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #endif Fancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); if (!skirmish) { Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); } else { Fancy_Text_Print(TXT_EASY, difficulty.X, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_TEXT); Fancy_Text_Print(TXT_HARD, difficulty.X + difficulty.Width, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_RIGHT|TPF_TEXT); Fancy_Text_Print(TXT_NORMAL, difficulty.X + difficulty.Width/2, difficulty.Y-8*RESFACTOR, scheme, TBLACK, TPF_CENTER|TPF_TEXT); } Fancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); Fancy_Text_Print(TXT_COUNT, d_count_x - 2, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print(TXT_LEVEL, d_level_x - 2, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | 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, d_color_y + 1, cbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2, ColorRemaps[i].Box); // (i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box); if (i == Session.ColorIdx) { Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false); } else { Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false); } } } /*.................................................................. Draw the message system; erase old messages first ..................................................................*/ if (display >= REDRAW_MESSAGE && !skirmish) { Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); } //.................................................................. // Update game parameter labels //.................................................................. if (display >= REDRAW_PARMS) { // LogicPage->Fill_Rect(d_count_x + d_count_w + 2, d_count_y, d_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK); sprintf(staticcountbuff, "%d", Session.Options.UnitCount); staticcount.Set_Text(staticcountbuff); staticcount.Draw_Me(); // Fancy_Text_Print("%d ", d_count_x + d_count_w + 3 * RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT, Session.Options.UnitCount); if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) { sprintf(staticlevelbuff, "%d ", BuildLevel); } else { sprintf(staticlevelbuff, "**"); } staticlevel.Set_Text(staticlevelbuff); staticlevel.Draw_Me(); // Fancy_Text_Print(txt, d_level_x + d_level_w + 3 * RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT); sprintf(staticcreditsbuff, "%d", Session.Options.Credits); staticcredits.Set_Text(staticcreditsbuff); staticcredits.Draw_Me(); // Fancy_Text_Print("%d", d_credits_x + d_credits_w + 2 * RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT, Session.Options.Credits); sprintf(staticaibuff, "%d", Session.Options.AIPlayers); staticai.Set_Text(staticaibuff); staticai.Draw_Me(); // Fancy_Text_Print("%d", d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT, Session.Options.AIPlayers); } /* .......................... Redraw buttons .......................... */ if (display >= REDRAW_BUTTONS) { commands->Flag_List_To_Redraw(); commands->Draw_All(); } Show_Mouse(); display = REDRAW_NONE; } /* ........................... Get user input ............................ */ messages_have_focus = Session.Messages.Has_Edit_Focus(); bool droplist_is_dropped = housebtn.IsDropped; input = commands->Input(); /* ** Sort out the input focus between the name edit box and the message system */ if (!skirmish) { if (messages_have_focus) { if (!name_edt.Has_Focus()) { Session.Messages.Set_Edit_Focus(); } else { messages_have_focus = false; display = REDRAW_MESSAGE; } } } /* ** Redraw everything if the droplist collapsed */ if (droplist_is_dropped && !housebtn.IsDropped) { display = REDRAW_BACKGROUND; } if (input & KN_BUTTON) { if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } } /* ---------------------------- Process input ---------------------------- */ switch (input) { /*------------------------------------------------------------------ User clicks on a color button ------------------------------------------------------------------*/ case KN_LMOUSE: if (Keyboard->MouseQX > cbox_x[0] && Keyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) && Keyboard->MouseQY > d_color_y && Keyboard->MouseQY < (d_color_y + d_color_h)) { Session.PrefColor = (PlayerColorType)((Keyboard->MouseQX - cbox_x[0]) / d_color_w); Session.ColorIdx = Session.PrefColor; if (display < REDRAW_COLORS) display = REDRAW_COLORS; name_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); name_edt.Flag_To_Redraw(); Session.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx); strcpy (Session.Handle, namebuf); transmit = true; changed = true; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } } break; /*------------------------------------------------------------------ User edits the name field; retransmit new game options ------------------------------------------------------------------*/ case (BUTTON_NAME | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } strcpy (Session.Handle, namebuf); transmit = true; changed = true; break; #ifdef OLDWAY /*------------------------------------------------------------------ House Buttons: set the player's desired House ------------------------------------------------------------------*/ case (BUTTON_GDI | KN_BUTTON): Session.House = HOUSE_GOOD; gdibtn.Turn_On(); nodbtn.Turn_Off(); strcpy (Session.Handle, namebuf); transmit = true; break; case (BUTTON_NOD | KN_BUTTON): Session.House = HOUSE_BAD; gdibtn.Turn_Off(); nodbtn.Turn_On(); strcpy (Session.Handle, namebuf); transmit = true; break; #else case (BUTTON_HOUSE | KN_BUTTON): Session.House = HousesType(housebtn.Current_Index()+HOUSE_USSR); strcpy (Session.Handle, namebuf); display = REDRAW_BACKGROUND; transmit = true; break; #endif /*------------------------------------------------------------------ New Scenario selected. ------------------------------------------------------------------*/ #ifdef FIXIT_VERSION_3 // All scenarios now allowable as downloads. ajw case (BUTTON_SCENARIOLIST | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } if (scenariolist.Current_Index() != Session.Options.ScenarioIndex) { Session.Options.ScenarioIndex = scenariolist.Current_Index(); strcpy (Session.Handle, namebuf); transmit = true; } break; #else // FIXIT_VERSION_3 Whoever duplicated Netdlg into Nulldlg should be shot. Wasn't it enough? Abandon all hope ye who hit enter here. case (BUTTON_SCENARIOLIST | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } if (scenariolist.Current_Index() != Session.Options.ScenarioIndex) { #ifdef FIXIT_CSII // checked - ajw if ( !skirmish && (PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) && #else if ( !skirmish && PlayingAgainstVersion < VERSION_RED_ALERT_107 && #endif Session.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){ scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex); Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200); Sound_Effect(VOC_SYS_ERROR); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; #ifdef FIXIT_CSII // checked - ajw } else if ( !skirmish && PlayingAgainstVersion < VERSION_AFTERMATH_CS && Is_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){ scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex); Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200); Sound_Effect(VOC_SYS_ERROR); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; #endif }else{ Session.Options.ScenarioIndex = scenariolist.Current_Index(); transmit = 1; } strcpy (Session.Handle, namebuf); transmit = true; } break; #endif /*------------------------------------------------------------------ User adjusts max # units ------------------------------------------------------------------*/ case (BUTTON_COUNT | KN_BUTTON): Session.Options.UnitCount = countgauge.Get_Value() + SessionClass::CountMin[Session.Options.Bases]; if (display < REDRAW_PARMS) display = REDRAW_PARMS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } transmit = true; 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; if (display < REDRAW_PARMS) display = REDRAW_PARMS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } transmit = true; break; /*------------------------------------------------------------------ User adjusts max # units ------------------------------------------------------------------*/ case (BUTTON_CREDITS | KN_BUTTON): Session.Options.Credits = creditsgauge.Get_Value(); Session.Options.Credits = ((Session.Options.Credits + 250) / 500) * 500; if (display < REDRAW_PARMS) display = REDRAW_PARMS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } transmit = true; break; //.................................................................. // User adjusts # of AI players //.................................................................. case (BUTTON_AIPLAYERS | KN_BUTTON): { Session.Options.AIPlayers = aiplayersgauge.Get_Value(); int humans = 2; // Two humans. if (skirmish) { Session.Options.AIPlayers += 1; // Always one forced AI player. humans = 1; // One human. // if (Session.Options.AIPlayers == 0) { // Session.Options.AIPlayers = 1; // aiplayersgauge.Set_Value(0); // } } if (Session.Options.AIPlayers+humans >= Rule.MaxPlayers) { // if it's pegged, max it out Session.Options.AIPlayers = Rule.MaxPlayers - humans; aiplayersgauge.Set_Value(Session.Options.AIPlayers - (skirmish ? 1 : 0)); } transmit = true; if (display < REDRAW_PARMS) display = REDRAW_PARMS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } break; } //------------------------------------------------------------------ // Toggle-able options: // If 'Bases' gets toggled, we have to change the range of the // UnitCount slider. // Also, if Tiberium gets toggled, we have to set the flags // in SpecialClass. //------------------------------------------------------------------ case (BUTTON_OPTIONS | KN_BUTTON): if (!skirmish && Special.IsCaptureTheFlag != optionlist.Is_Checked(4) && !Special.IsCaptureTheFlag) { optionlist.Check_Item(0, true); } if (Session.Options.Bases != optionlist.Is_Checked(0)) { Session.Options.Bases = optionlist.Is_Checked(0); if (Session.Options.Bases) { Session.Options.UnitCount = Fixed_To_Cardinal ( SessionClass::CountMax[1] - SessionClass::CountMin[1], Cardinal_To_Fixed( SessionClass::CountMax[0]-SessionClass::CountMin[0], Session.Options.UnitCount-SessionClass::CountMin[0])) + SessionClass::CountMin[1]; } else { if (!skirmish) optionlist.Check_Item(4, false); Session.Options.UnitCount = Fixed_To_Cardinal ( SessionClass::CountMax[0] - SessionClass::CountMin[0], Cardinal_To_Fixed( SessionClass::CountMax[1]-SessionClass::CountMin[1], Session.Options.UnitCount - SessionClass::CountMin[1])) + SessionClass::CountMin[0]; } countgauge.Set_Maximum( SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); } Session.Options.Tiberium = optionlist.Is_Checked(1); Special.IsTGrowth = Session.Options.Tiberium; Rule.IsTGrowth = Session.Options.Tiberium; Special.IsTSpread = Session.Options.Tiberium; Rule.IsTSpread = Session.Options.Tiberium; Session.Options.Goodies = optionlist.Is_Checked(2); Special.IsShadowGrow = optionlist.Is_Checked(3); if (!skirmish) { Special.IsCaptureTheFlag = optionlist.Is_Checked(4); } transmit = true; if (display < REDRAW_PARMS) display = REDRAW_PARMS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } break; /*------------------------------------------------------------------ OK: exit loop with true status ------------------------------------------------------------------*/ case (BUTTON_LOAD | KN_BUTTON): case (BUTTON_OK | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } // // 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 = true; transmittime = 0; } else { WWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL); display = REDRAW_ALL; } if (input==(BUTTON_LOAD | KN_BUTTON)) load_game = true; break; /*------------------------------------------------------------------ CANCEL: send a SIGN_OFF, bail out with error code ------------------------------------------------------------------*/ case (KN_ESC): case (BUTTON_CANCEL | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } process = false; rc = false; break; /*------------------------------------------------------------------ Default: manage the inter-player messages ------------------------------------------------------------------*/ default: if (!skirmish) { if (Session.Messages.Manage()) { if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; } /*............................................................... Service keyboard input for any message being edited. ...............................................................*/ i = Session.Messages.Input(input); /*............................................................... If 'Input' returned 1, it means refresh the message display. (We have to redraw the edit line, to erase the cursor.) ...............................................................*/ if (i==1) { Hide_Mouse(); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); Show_Mouse(); } else if (i==2) { /*............................................................... If 'Input' returned 2, it means redraw the message display. Rather than setting 'display', which would redraw all msgs, we only need to erase & redraw the edit box here. ...............................................................*/ Hide_Mouse(); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); Show_Mouse(); } else if (i==3 || i==4) { /*............................................................... If 'input' returned 3, it means send the current message. ...............................................................*/ memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_MESSAGE; strcpy (SendPacket.Name, namebuf); SendPacket.ID = Session.ColorIdx; if (i==3) { strcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf()); } else { strcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf()); Session.Messages.Clear_Overflow_Buf(); } /*.................................................................. Send the message ..................................................................*/ if (!skirmish) { NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); NullModem.Service(); } /*.................................................................. Add the message to our own screen ..................................................................*/ Session.Messages.Add_Message (SendPacket.Name, SendPacket.ID, SendPacket.Message.Message, (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, -1); Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, NULL, '_', d_message_w); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; } /* end of send message */ } break; } /*--------------------------------------------------------------------- Detect editing of the name buffer, transmit new values to players ---------------------------------------------------------------------*/ if (strcmp (namebuf, Session.Handle)) { strcpy (Session.Handle, namebuf); transmit = true; changed = true; } /*--------------------------------------------------------------------- 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 (skirmish) { transmit = false; } if (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) { memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_GAME_OPTIONS; strcpy (SendPacket.Name, namebuf); SendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID(); SendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version(); SendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version(); SendPacket.ScenarioInfo.House = Session.House; SendPacket.ScenarioInfo.Color = Session.ColorIdx; SendPacket.ScenarioInfo.Credits = Session.Options.Credits; SendPacket.ScenarioInfo.IsBases = Session.Options.Bases; SendPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium; SendPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies; SendPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers; SendPacket.ScenarioInfo.BuildLevel = BuildLevel; SendPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount; SendPacket.ScenarioInfo.Seed = Seed; SendPacket.ScenarioInfo.Special = Special; SendPacket.ScenarioInfo.GameSpeed = Options.GameSpeed; SendPacket.ID = Session.ModemType; /* ** Set up the scenario info so the remote player can match the scenario on his machine ** or request a download if it doesnt exist */ strcpy (SendPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description()); CCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); SendPacket.ScenarioInfo.FileLength = file.Size(); #ifdef WOLAPI_INTEGRATION strcpy( SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() ); #else strncpy (SendPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(SendPacket.ScenarioInfo.ShortFileName)); #endif strncpy ((char*)SendPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof SendPacket.ScenarioInfo.FileDigest); SendPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official(); NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); transmittime = TickCount; transmit = false; //.................................................................. // Keep the player list up to date //.................................................................. if (playerlist.Count()) { item = (char *)playerlist.Get_Item(0); #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); #endif //OLDWAY playerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]; playerlist.Flag_To_Redraw(); } //.................................................................. // Play a little sound effect //.................................................................. Sound_Effect(VOC_OPTIONS_CHANGED); } // // send a timing packet if enough time has gone by. // if (!skirmish && (TickCount - timingtime) > PACKET_TIMING_TIMEOUT) { memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_TIMING; SendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time(); SendPacket.ID = Session.ModemType; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0); timingtime = TickCount; } /*--------------------------------------------------------------------- Check for an incoming message ---------------------------------------------------------------------*/ if (!skirmish && NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) { lastmsgtime = TickCount; 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 == Session.ModemType) { WWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING); // to skip the other system not responding msg lastmsgtime = TickCount; 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 - lastredrawtime) > PACKET_REDRAW_TIME) { lastredrawtime = TickCount; oppscorescreen = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; parms_received = true; } } 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; while (TickCount - starttime < 60) NullModem.Service(); WWMessageBox().Process(TXT_USER_SIGNED_OFF); // to skip the other system not responding msg lastmsgtime = TickCount; 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; kludge_timer = 2*60; strcpy (TheirName, ReceivePacket.Name); TheirColor = ReceivePacket.ScenarioInfo.Color; TheirHouse = ReceivePacket.ScenarioInfo.House; transmit = true; parms_received = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; //......................................................... // "Clip" the other system's version range to our own // ........................................................ version = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion, ReceivePacket.ScenarioInfo.MaxVersion); // ........................................................ // If the greatest-common-version comes back 0, the other // system's range is too low for ours // ........................................................ if (version == 0) { WWMessageBox().Process (TXT_DESTGAME_OUTDATED); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } else if (version == 0xffffffff) { // ........................................................ // If the greatest-common-version comes back 0xffffffff, // the other system's range is too high for ours // ........................................................ WWMessageBox().Process (TXT_YOURGAME_OUTDATED); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } else { if (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) { WWMessageBox().Process (TXT_MISMATCH); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } else { // ........................................................ // Otherwise, 'version' is the highest version we have in // common; look up the protocol that goes with this version. // ........................................................ Session.CommProtocol = VerNum.Version_Protocol(version); #ifndef FIXIT_VERSION_3 PlayingAgainstVersion = version; #endif } } /*......................................................... If this is the first game-options packet we've received, init the game & player lists .........................................................*/ if (playerlist.Count()==0) { //...................................................... // Add two strings to the player list //...................................................... item = new char [MPLAYER_NAME_MAX + 64]; //Need room to display country name playerlist.Add_Item(item, &ColorRemaps[Session.ColorIdx]); item = new char [MPLAYER_NAME_MAX + 64]; //Need room to display country name playerlist.Add_Item(item, &ColorRemaps[TheirColor]); } //......................................................... // Ensure the player list has the latest, greatest copy of // our names & colors. Do this every time we receive an // options packet. //......................................................... item = (char *)playerlist.Get_Item(0); #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); #endif //OLDWAY playerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]; item = (char *)playerlist.Get_Item(1); #ifdef OLDWAY if (TheirHouse==HOUSE_GOOD) { sprintf(item,"%s\t%s",TheirName, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",TheirName, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name())); #endif //OLDWAY playerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor]; playerlist.Flag_To_Redraw(); //......................................................... // Play a little sound effect //......................................................... Sound_Effect(VOC_OPTIONS_CHANGED); break; /*.................................................................. Incoming message: add to our list ..................................................................*/ case (SERIAL_MESSAGE): oppscorescreen = false; Session.Messages.Add_Message (ReceivePacket.Name, ((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID, ReceivePacket.Message.Message, ((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID, TPF_TEXT, -1); Sound_Effect(VOC_INCOMING_MESSAGE); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; break; // // get their response time // case (SERIAL_TIMING): oppscorescreen = false; theirresponsetime = ReceivePacket.ScenarioInfo.ResponseTime; if ( !gameoptions ) { // retransmit of game options packet again transmit = true; } break; // // print msg waiting for opponent // case (SERIAL_SCORE_SCREEN): oppscorescreen = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; parms_received = true; break; default: break; } } } // if we haven't received a msg for 10 seconds exit if (!skirmish && (TickCount - lastmsgtime) > msg_timeout) { WWMessageBox().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 ---------------------------------------------------------------------*/ if (!skirmish) { NullModem.Service(); } } /*------------------------------------------------------------------------ Prepare to load the scenario ------------------------------------------------------------------------*/ if (rc) { Session.NumPlayers = skirmish ? 1 : 2; Scen.Scenario = Session.Options.ScenarioIndex; strcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); /*..................................................................... Add both players to the Players vector; the local system is always index 0. .....................................................................*/ who = new NodeNameType; strcpy(who->Name, namebuf); who->Player.House = Session.House; who->Player.Color = Session.ColorIdx; who->Player.ProcessTime = -1; Session.Players.Add (who); /* ** Fetch the difficulty setting when in skirmish mode. */ if (skirmish) { int diff = difficulty.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2); switch (diff) { case 0: Scen.CDifficulty = DIFF_HARD; Scen.Difficulty = DIFF_EASY; break; case 1: Scen.CDifficulty = DIFF_HARD; Scen.Difficulty = DIFF_NORMAL; break; case 2: Scen.CDifficulty = DIFF_NORMAL; Scen.Difficulty = DIFF_NORMAL; break; case 3: Scen.CDifficulty = DIFF_EASY; Scen.Difficulty = DIFF_NORMAL; break; case 4: Scen.CDifficulty = DIFF_EASY; Scen.Difficulty = DIFF_HARD; break; } } else { Scen.CDifficulty = DIFF_NORMAL; Scen.Difficulty = DIFF_NORMAL; } if (!skirmish) { who = new NodeNameType; #ifdef FIXIT_MODEM_LOAD_CRASH /* If the names of the players are the same then we MUST force them * be be unique. This is necessary to prevent a crash after loading * a modem save game. */ if (strcmp(TheirName, namebuf) == 0) { if (strlen(TheirName) == (MPLAYER_NAME_MAX - 1)) { TheirName[MPLAYER_NAME_MAX - 1] = '\0'; } else { strcat(TheirName, "2"); } } #endif strcpy(who->Name, TheirName); who->Player.House = TheirHouse; who->Player.Color = TheirColor; who->Player.ProcessTime = -1; Session.Players.Add (who); } /*..................................................................... Send all players a GO packet. .....................................................................*/ memset (&SendPacket, 0, sizeof(SerialPacketType)); if (load_game) { SendPacket.Command = SERIAL_LOADGAME; } else { SendPacket.Command = SERIAL_GO; } if (!skirmish) { SendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time(); if ( theirresponsetime == 10000 ) { ; } else if (SendPacket.ScenarioInfo.ResponseTime < theirresponsetime) { SendPacket.ScenarioInfo.ResponseTime = theirresponsetime; } } // // calculated one way delay for a packet and overall delay to execute // a packet // if (!skirmish) { if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) { Session.MaxAhead = max( ((((SendPacket.ScenarioInfo.ResponseTime / 8) + (Session.FrameSendRate - 1)) / Session.FrameSendRate) * Session.FrameSendRate), (Session.FrameSendRate * 2) ); } else { Session.MaxAhead = max( (SendPacket.ScenarioInfo.ResponseTime / 8), MODEM_MIN_MAX_AHEAD ); } } SendPacket.ID = Session.ModemType; if (!skirmish) { NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); starttime = TickCount; while ( ( NullModem.Num_Send() && ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) ) || ((TickCount - starttime) < 60) ) { #if(SHOW_MONO) NullModem.Mono_Debug_Print(0); #endif NullModem.Service(); } /* ** Wait for the go response. This will be either a 'GO' reply, a ** request for the scenario to be sent or a reply to say that the scenario ** cant be played. */ #ifdef WIN32 WWDebugString ("RA95 - About to wait for 'GO' response.\n"); #endif do { NullModem.Service(); if (NullModem.Get_Message (&ReceivePacket, &packetlen) > 0) { #ifdef FIXIT_VERSION_3 if (ReceivePacket.Command == SERIAL_READY_TO_GO) { if( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() ) { if( !Force_Scenario_Available( Scen.ScenarioName ) ) Emergency_Exit(EXIT_FAILURE); } break; } #else if (ReceivePacket.Command == SERIAL_READY_TO_GO) break; #endif if (ReceivePacket.Command == SERIAL_NO_SCENARIO) { WWMessageBox().Process(TXT_NO_EXPANSION_SCENARIO, TXT_CANCEL); /* ** We have to recover from this somehow so.... */ process = true; display = REDRAW_ALL; lastmsgtime = TickCount; goto oh_dear_its_a_label; } if (ReceivePacket.Command == SERIAL_REQ_SCENARIO) { #ifdef WIN32 WWDebugString ("RA95 - About to call 'Send_Remote_File'.\n"); #endif #ifdef FIXIT_VERSION_3 if( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() ) { if( !Force_Scenario_Available( Scen.ScenarioName ) ) Emergency_Exit(EXIT_FAILURE); } #endif Send_Remote_File (Scen.ScenarioName, 0); break; } } } while ( !Keyboard->Check() ); // clear queue to keep from doing any resends NullModem.Init_Send_Queue(); } } else { if ( !recsignedoff ) { /*..................................................................... Broadcast my sign-off over my network .....................................................................*/ if (!skirmish) { memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_SIGN_OFF; SendPacket.ScenarioInfo.Color = Session.ColorIdx; // use Color for ID SendPacket.ID = Session.ModemType; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); starttime = TickCount; while ( (NullModem.Num_Send() && ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) ) || ((TickCount - 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 == Session.ModemType) { // exit while break; } } NullModem.Service(); } } } if (!skirmish) Shutdown_Modem(); } /*------------------------------------------------------------------------ Clear all lists ------------------------------------------------------------------------*/ while (scenariolist.Count()) { scenariolist.Remove_Item(scenariolist.Get_Item(0)); } /*------------------------------------------------------------------------ Clean up the list boxes ------------------------------------------------------------------------*/ while (playerlist.Count()>0) { item = (char *)playerlist.Get_Item(0); delete [] item; playerlist.Remove_Item(item); } /*------------------------------------------------------------------------ Remove the chat edit box ------------------------------------------------------------------------*/ Session.Messages.Remove_Edit(); /*------------------------------------------------------------------------ Restore screen ------------------------------------------------------------------------*/ Hide_Mouse(); Load_Title_Page(true); Show_Mouse(); /*------------------------------------------------------------------------ Save any changes made to our options ------------------------------------------------------------------------*/ if (changed) { Session.Write_MultiPlayer_Settings(); } if (load_game && !skirmish) { if (!Load_Game (-1)) { WWMessageBox().Process (TXT_ERROR_LOADING_GAME); rc = false; } Frame++; } return(rc); } #ifdef FIXIT_CSII // checked - ajw 9/28/98 extern bool Is_Mission_Aftermath (char *file_name); #endif /*********************************************************************************************** * Find_Local_Scenario -- finds the file name of the scenario with matching attributes * * * * * * * * INPUT: ptr to Scenario description * * ptr to Scenario filename to fix up * * length of file for trivial rejection of scenario files * * ptr to digest. Digests must match. * * * * * * OUTPUT: true if scenario is available locally * * * * WARNINGS: We need to reject files that don't match exactly because scenarios with the same * * description can exist on both machines but have different contents. For example * * there will be lots of scenarios called 'my map' and 'aaaaaa'. * * * * HISTORY: * * 8/23/96 12:36PM ST : Created * *=============================================================================================*/ bool Find_Local_Scenario (char *description, char *filename, unsigned int length, char *digest, bool official) { //FILE *fp; //fp = fopen("findscen.txt","wt"); //debugprint("looking for local scenario: description = %s, name=%s, length=%d, digest=%s, official=%d\n", description, filename, length, digest, official); char digest_buffer[32]; /* ** Scan through the scenario list looking for scenarios with matching descriptions. */ for (int index = 0; index < Session.Scenarios.Count(); index++) { //debugprint( "Checking against scenario: %s\n", Session.Scenarios[index]->Description()); if (!strcmp (Session.Scenarios[index]->Description(), description)) { //debugprint("found matching description.\n"); CCFileClass file (Session.Scenarios[index]->Get_Filename()); /* ** Possible rejection on the basis of availability. */ if (file.Is_Available()) { //debugprint("file is available.\n"); /* ** Possible rejection on the basis of size. */ if (file.Size() == length) { //debugprint("length matches.\n"); /* ** We don't know the digest for 'official' scenarios so assume its correct */ if (!official) { //debugprint("!official.\n"); /* ** Possible rejection on the basis of digest */ INIClass ini; ini.Load(file); ini.Get_String ("Digest", "1", "No digest here mate. Nope.", digest_buffer, sizeof (digest_buffer) ); } //debugprint("digest = %s, digest_buffer = %s.\n", digest, digest_buffer); #ifdef FIXIT_CSII // checked - ajw 9/28/98. But don't know why this happens. Because of autodownload? /* ** If this is an aftermath scenario then ignore the digest and return success. */ if ( Is_Mission_Aftermath ((char*)Session.Scenarios[index]->Get_Filename()) ) { //debugprint("a 1match!\n"); strcpy (filename, Session.Scenarios[index]->Get_Filename()); return (true); } #endif /* ** This must be the same scenario. Copy the name and return true. */ if (official || !strcmp (digest, digest_buffer)) { //debugprint("a match!\n"); strcpy (filename, Session.Scenarios[index]->Get_Filename()); return (true); } } } // else // debugprint("file not available '%s'.\n", Session.Scenarios[index]->Get_Filename()); } } //debugprint("failed match.\n"); /* ** Couldnt find the scenario locally. Return failure. */ return (false); } /*********************************************************************************************** * Com_Show_Scenario_Dialog -- Serial game scenario selection dialog * * * * The 'Players' vector is filled in by this routine, when the game starts; this * * is for the Assign_Houses routine, which expects this vector to contain all * * players' names & houses & colors. Other than that, the Players vector, Games * * vector, and Chat vector aren't used at all by this routine. The Game & Players * * list boxes are filled in manually in the processing loop. * * * * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ * * ³ Serial Game ³ * * ³ ³ * * ³ Your Name: __________ ³ * * ³ House: [GDI] [NOD] ³ * * ³ Desired Color: [ ][ ][ ][ ] ³ * * ³ ³ * * ³ Opponent: Name ³ * * ³ Scenario: Description ³ * * ³ Credits: xxxx ³ * * ³ Bases: ON ³ * * ³ Crates: ON ³ * * ³ Tiberium: ON ³ * * ³ Ghosts: ON ³ * * ³ ³ * * ³ [Cancel] ³ * * ³ ³ * * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * * ³ ³ ³ ³ * * ³ ³ ³ ³ * * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * * ³ [Send Message] ³ * * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ * * * * INPUT: * * none. * * * * OUTPUT: * * true = success, false = cancel * * * * WARNINGS: * * none. * * * * HISTORY: * * 02/14/1995 BR : Created. * *=============================================================================================*/ int Com_Show_Scenario_Dialog(void) { /*........................................................................ Dialog & button dimensions ........................................................................*/ int d_dialog_w = 320 * RESFACTOR; // dialog width int d_dialog_h = 200 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = ((200 * RESFACTOR - 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 * RESFACTOR+1; // ht of 6-pt text int d_margin1 = 5 * RESFACTOR; // margin width/height int d_margin2 = 2 * RESFACTOR; // margin width/height int d_name_w = 70 * RESFACTOR; int d_name_h = 9 * RESFACTOR; int d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2); int d_name_y = d_dialog_y + d_margin1 + d_margin2 + d_txt6_h + 1*RESFACTOR; #ifdef OLDWAY int d_gdi_w = 40 * RESFACTOR; int d_gdi_h = 9 * RESFACTOR; int d_gdi_x = d_dialog_cx - d_gdi_w; int d_gdi_y = d_name_y; int d_nod_w = 40 * RESFACTOR; int d_nod_h = 9 * RESFACTOR; int d_nod_x = d_dialog_cx; int d_nod_y = d_name_y; #else //OLDWAY int d_house_w = 60 *RESFACTOR; int d_house_h = (8 * 5 *RESFACTOR); int d_house_x = d_dialog_cx - (d_house_w / 2); int d_house_y = d_name_y; #endif //OLDWAY int d_color_w = 10 * RESFACTOR; int d_color_h = 9 * RESFACTOR; int d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3); int d_color_y = d_name_y; int d_scenario_y = d_name_y + d_name_h + d_margin2; int d_gamelist_w = 160 * RESFACTOR; int d_gamelist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR; // 6 rows high int d_gamelist_x = d_dialog_x + d_margin1 + 10*RESFACTOR; int d_gamelist_y = d_scenario_y + d_txt6_h + d_margin2 + d_txt6_h + d_margin2; //BG int d_playerlist_w = 112 * RESFACTOR; int d_playerlist_w = 118 * RESFACTOR; int d_playerlist_h = (6 * 6 * RESFACTOR) + 3 * RESFACTOR; // 6 rows high int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w - 5*RESFACTOR; int d_playerlist_y = d_gamelist_y; int d_count_w = 25 * RESFACTOR; int d_count_h = d_txt6_h; int d_count_x = d_gamelist_x + (d_gamelist_w / 2); int d_count_y = d_gamelist_y + d_gamelist_h + (d_margin1 * 2) - d_margin2; int d_level_w = 25 * RESFACTOR; int d_level_h = d_txt6_h; int d_level_x = d_gamelist_x + (d_gamelist_w / 2); int d_level_y = d_count_y + d_count_h; int d_credits_w = 25 * RESFACTOR; int d_credits_h = d_txt6_h; int d_credits_x = d_gamelist_x + (d_gamelist_w / 2); int d_credits_y = d_level_y + d_level_h; int d_aiplayers_w = 25 * RESFACTOR; int d_aiplayers_h = d_txt6_h; int d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2); int d_aiplayers_y = d_credits_y + d_credits_h; int d_options_w = 112 * RESFACTOR; int d_options_h = (5 * 6* RESFACTOR) + 4*RESFACTOR; int d_options_x = d_playerlist_x; int d_options_y = d_playerlist_y + d_playerlist_h + d_margin1 - d_margin2; int d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR; int d_message_h = (7 * d_txt6_h) + 3 * RESFACTOR; // 7 rows high int d_message_x = d_gamelist_x;//d_dialog_x + d_margin1 + 10*RESFACTOR; int d_message_y = d_options_y + d_options_h + d_margin2/*KO + d_margin1*/; int d_send_w = d_message_w; int d_send_h = 9 * RESFACTOR; int d_send_x = d_message_x; int d_send_y = d_message_y + d_message_h; int d_cancel_w = 45 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; int d_cancel_x = d_dialog_cx - (d_cancel_w / 2); int d_cancel_y = d_send_y + d_send_h/*KO + d_margin2*/; /*........................................................................ Button Enumerations ........................................................................*/ enum { BUTTON_NAME = 100, #ifdef OLDWAY BUTTON_GDI, BUTTON_NOD, #else //OLDWAY BUTTON_HOUSE, #endif //OLDWAY BUTTON_GAMELIST, BUTTON_PLAYERLIST, BUTTON_CANCEL, BUTTON_COUNT, BUTTON_LEVEL, BUTTON_CREDITS, BUTTON_AI_PLAYERS, BUTTON_OPTIONS, }; /*........................................................................ Redraw values: in order from "top" to "bottom" layer of the dialog ........................................................................*/ typedef enum { REDRAW_NONE = 0, REDRAW_PARMS, REDRAW_MESSAGE, REDRAW_COLORS, REDRAW_BUTTONS, REDRAW_BACKGROUND, REDRAW_ALL = REDRAW_BACKGROUND } RedrawType; /*........................................................................ Dialog variables ........................................................................*/ RedrawType display = REDRAW_ALL; // redraw level int cbox_x[] = { d_color_x, d_color_x + d_color_w, d_color_x + (d_color_w * 2), d_color_x + (d_color_w * 3), d_color_x + (d_color_w * 4), d_color_x + (d_color_w * 5), d_color_x + (d_color_w * 6), d_color_x + (d_color_w * 7) }; char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name //BG int playertabs[] = {77}; // tabs for player list box int playertabs[] = {71*RESFACTOR}; // tabs for player list box int optiontabs[] = {8}; // tabs for options list box bool transmit; // 1 = re-transmit new game options bool first; // 1 = no packets received yet bool parms_received = false; // 1 = game options received bool changed = false; // 1 = user has changed an option int rc; int recsignedoff = 0; int i; unsigned long 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 bool load_game = false; // 1 = load saved game NodeNameType *who; // node to add to Players char *item; // for filling in lists char *p; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); Session.Options.ScenarioDescription[0] = 0; //Flag that we dont know the scenario name yet bool messages_have_focus = true; bool ready_packet_was_sent = false; /*........................................................................ Buttons ........................................................................*/ GadgetClass *commands; // button list EditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC); #ifdef OLDWAY TextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h); TextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w, d_nod_h); #else //OLDWAY char housetext[25] = ""; Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT); DropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext), TPF_TEXT, d_house_x, d_house_y, d_house_w, d_house_h, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); #endif //OLDWAY TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w); ListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h); char staticcountbuff[35]; StaticButtonClass staticcount(0, " ", TPF_TEXT, d_count_x+d_count_w+3*RESFACTOR, d_count_y); GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h); char staticlevelbuff[35]; StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x+d_level_w+3*RESFACTOR, d_level_y); GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h); char staticcreditsbuff[35]; StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x+d_credits_w+3*RESFACTOR, d_credits_y); GaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h); char staticaibuff[35]; StaticButtonClass staticai(0, " ", TPF_TEXT, d_aiplayers_x+d_aiplayers_w+3*RESFACTOR, d_aiplayers_y); CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); /* ------------------------- Build the button list -------------------------- */ commands = &name_edt; staticcount.Add_Tail(*commands); staticcredits.Add_Tail(*commands); staticai.Add_Tail(*commands); staticlevel.Add_Tail(*commands); cancelbtn.Add_Tail(*commands); gamelist.Add_Tail(*commands); playerlist.Add_Tail(*commands); countgauge.Add_Tail(*commands); levelgauge.Add_Tail(*commands); creditsgauge.Add_Tail(*commands); aiplayersgauge.Add_Tail(*commands); optionlist.Add_Tail(*commands); #ifdef OLDWAY gdibtn.Add_Tail(*commands); nodbtn.Add_Tail(*commands); #else //OLDWAY housebtn.Add_Tail(*commands); #endif //OLDWAY //------------------------------------------------------------------------ // Init the button states //------------------------------------------------------------------------ //........................................................................ // Name & Color //........................................................................ Session.ColorIdx = Session.PrefColor; // init my preferred color strcpy (namebuf, Session.Handle); // set my name name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX); name_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); //........................................................................ // List boxes //........................................................................ playerlist.Set_Tabs(playertabs); playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL); optionlist.Set_Tabs(optiontabs); optionlist.Set_Read_Only(1); optionlist.Add_Item(Text_String(TXT_BASES)); optionlist.Add_Item(Text_String(TXT_ORE_SPREADS)); optionlist.Add_Item(Text_String(TXT_CRATES)); optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG)); optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS)); optionlist.Check_Item(0, Session.Options.Bases); optionlist.Check_Item(1, Session.Options.Tiberium); optionlist.Check_Item(2, Session.Options.Goodies); optionlist.Check_Item(3, Special.IsCaptureTheFlag); optionlist.Check_Item(4, Special.IsShadowGrow); //........................................................................ // House buttons //........................................................................ #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { gdibtn.Turn_On(); } else { nodbtn.Turn_On(); } #else //OLDWAY for (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) { housebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name())); } housebtn.Set_Selected_Index(Session.House - HOUSE_USSR); housebtn.Set_Read_Only (true); #endif //OLDWAY //........................................................................ // Option gauges //........................................................................ countgauge.Use_Thumb(0); countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); levelgauge.Use_Thumb(0); levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1); levelgauge.Set_Value(BuildLevel - 1); creditsgauge.Use_Thumb(0); creditsgauge.Set_Maximum(Rule.MPMaxMoney); creditsgauge.Set_Value(Session.Options.Credits); aiplayersgauge.Use_Thumb(0); aiplayersgauge.Set_Maximum(Rule.MaxPlayers-2); aiplayersgauge.Set_Value(Session.Options.AIPlayers); Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT); transmit = true; first = true; /*........................................................................ Clear the Players vector ........................................................................*/ Clear_Vector(&Session.Players); /*........................................................................ Init the message display system ........................................................................*/ Session.Messages.Init (d_message_x + 1, d_message_y + 1, 7, MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 * RESFACTOR, d_send_y + 1 * RESFACTOR, 1, 20, MAX_MESSAGE_LENGTH - 5, d_message_w); Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, NULL, '_', d_message_w); Session.WWChat = 0; /*........................................................................ Init version number clipping system ........................................................................*/ VerNum.Init_Clipping(); Load_Title_Page(true); CCPalette.Set(); extern char ModemRXString[]; if (strlen(ModemRXString) > 36) ModemRXString[36] = 0; if (strlen(ModemRXString) > 0) Session.Messages.Add_Message (NULL, 0, ModemRXString, PCOLOR_BROWN, TPF_TEXT, -1); ModemRXString[0] = '\0'; /* ---------------------------- Init Mono Output ---------------------------- */ #if(SHOW_MONO) NullModem.Configure_Debug(sizeof (CommHeaderType),sizeof (SerialCommandType), SerialPacketNames, 100, 8); NullModem.Mono_Debug_Print(1); #endif /* ---------------------------- Processing loop ----------------------------- */ NullModem.Reset_Response_Time(); // clear response time timingtime = lastmsgtime = lastredrawtime = TickCount; bool process = true; // process while true while (process) { #if(SHOW_MONO) NullModem.Mono_Debug_Print(0); #endif /* ** Kludge to make sure we redraw the message input line when it loses focus. ** If we dont do this then the cursor doesnt disappear. */ if (messages_have_focus) { if (name_edt.Has_Focus()) { if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; messages_have_focus = false; } } else { if (!name_edt.Has_Focus()) { messages_have_focus = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; Session.Messages.Set_Edit_Focus(); } } /* ........................ Invoke game callback ......................... */ Call_Back(); #ifdef WIN32 /* ** 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; } #endif /* ...................... Refresh display if needed ...................... */ if (display) { if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } 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 ...............................................................*/ Fancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); Fancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #ifdef OLDWAY Fancy_Text_Print(TXT_SIDE_COLON, d_gdi_x + d_gdi_w, d_gdi_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #else Fancy_Text_Print(TXT_SIDE_COLON, d_house_x + (d_house_w / 2), d_house_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); #endif Fancy_Text_Print(TXT_COLOR_COLON, d_dialog_x + ((d_dialog_w / 4) * 3), d_color_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); Fancy_Text_Print (TXT_COUNT, d_count_x - 2 * RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print (TXT_LEVEL, d_level_x - 2 * RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print (TXT_CREDITS_COLON, d_credits_x - 2 * RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); Fancy_Text_Print (TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | 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 * RESFACTOR, d_color_y + 1 * RESFACTOR, cbox_x[i] + 1 * RESFACTOR + d_color_w - 2 * RESFACTOR, d_color_y + 1 * RESFACTOR + d_color_h - 2 * RESFACTOR, ColorRemaps[i].Box); // (i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box); if (i == Session.ColorIdx) { Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false); } else { Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false); } } } /*.................................................................. Draw the message system; erase old messages first ..................................................................*/ if (display >= REDRAW_MESSAGE) { Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); //.................................................................. // Redraw the game options //.................................................................. if (display >= REDRAW_PARMS && 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, d_scenario_y, scheme, TBLACK, TPF_CENTER | TPF_TEXT); } else { /*............................................................ Scenario description ............................................................*/ //LogicPage->Fill_Rect(d_dialog_x + 16*RESFACTOR, d_scenario_y, // d_dialog_x + d_dialog_w - 16*RESFACTOR, d_scenario_y + d_txt6_h, BLACK); p = (char *)Text_String(TXT_SCENARIO_COLON); if (Session.Options.ScenarioDescription[0]) { // sprintf(txt,"%s %s",p, Session.Options.ScenarioDescription); // Fancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER); // EW - Scenario language translation goes here!!!!!!!! VG for (i = 0; EngMisStr[i] != NULL; i++) { if (!strcmp(Session.Options.ScenarioDescription, EngMisStr[i])) { #if defined(GERMAN) || defined(FRENCH) sprintf(txt, "%s %s", p, EngMisStr[i+1]); #else sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription); #endif break; } } if (EngMisStr[i] == NULL) { sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription); } Fancy_Text_Print (txt, d_dialog_cx, d_scenario_y, scheme, TBLACK, TPF_TEXT | TPF_CENTER); } else { sprintf(txt,"%s %s",p,Text_String(TXT_NOT_FOUND)); Fancy_Text_Print (txt, d_dialog_cx, d_scenario_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER); } //......................................................... // Unit count, tech level, credits //......................................................... //LogicPage->Fill_Rect(d_count_x + d_count_w + 2 * RESFACTOR, d_count_y, // d_count_x + d_count_w + 35 * RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, // BLACK); sprintf(staticcountbuff, "%d", Session.Options.UnitCount); staticcount.Set_Text(staticcountbuff); staticcount.Draw_Me(); if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) { sprintf(staticlevelbuff, "%d ", BuildLevel); } else { sprintf(staticlevelbuff, "**"); } staticlevel.Set_Text(staticlevelbuff); staticlevel.Draw_Me(); sprintf(staticcreditsbuff, "%d", Session.Options.Credits); staticcredits.Set_Text(staticcreditsbuff); staticcredits.Draw_Me(); sprintf(staticaibuff, "%d", Session.Options.AIPlayers); staticai.Set_Text(staticaibuff); staticai.Draw_Me(); } } } /* .......................... Redraw buttons .......................... */ if (display >= REDRAW_BUTTONS) { commands->Flag_List_To_Redraw(); } Show_Mouse(); display = REDRAW_NONE; } /* ........................... Get user input ............................ */ messages_have_focus = Session.Messages.Has_Edit_Focus(); bool droplist_is_dropped = housebtn.IsDropped; KeyNumType input = commands->Input(); /* ** Sort out the input focus between the name edit box and the message system */ if (messages_have_focus) { if (!name_edt.Has_Focus()) { Session.Messages.Set_Edit_Focus(); } else { messages_have_focus = false; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; } } /* ** Redraw everything if the droplist collapsed */ if (droplist_is_dropped && !housebtn.IsDropped) { display = REDRAW_BACKGROUND; } /* ---------------------------- Process input ---------------------------- */ switch (input) { /*------------------------------------------------------------------ User clicks on a color button ------------------------------------------------------------------*/ case KN_LMOUSE: if (Keyboard->MouseQX > cbox_x[0] && Keyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) && Keyboard->MouseQY > d_color_y && Keyboard->MouseQY < (d_color_y + d_color_h)) { /*......................................................... Compute my preferred color as the one I clicked on. .........................................................*/ Session.PrefColor = (PlayerColorType) ((Keyboard->MouseQX - cbox_x[0]) / d_color_w); changed = true; /*......................................................... If 'TheirColor' is set to the other player's color, make sure we can't pick that color. .........................................................*/ if (parms_received) { if (Session.PrefColor == TheirColor) break; } Session.ColorIdx = Session.PrefColor; name_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); name_edt.Flag_To_Redraw(); Session.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx); if (display < REDRAW_COLORS) display = REDRAW_COLORS; strcpy (Session.Handle, namebuf); transmit = true; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } } else if ( (Get_Mouse_X() >= d_count_x && Get_Mouse_X() <= d_count_x + d_count_w && Get_Mouse_Y() >= d_count_y && Get_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) || (Get_Mouse_X() >= d_options_x && Get_Mouse_X() <= d_options_x + d_options_w && Get_Mouse_Y() >= d_options_y && Get_Mouse_Y() <= d_options_y + d_options_h) ) { Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200); Sound_Effect(VOC_SYS_ERROR); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } } break; #ifdef OLDWAY /*------------------------------------------------------------------ House Buttons: set the player's desired House ------------------------------------------------------------------*/ case (BUTTON_GDI | KN_BUTTON): Session.House = HOUSE_GOOD; gdibtn.Turn_On(); nodbtn.Turn_Off(); strcpy (Session.Handle, namebuf); transmit = true; break; case (BUTTON_NOD | KN_BUTTON): Session.House = HOUSE_BAD; gdibtn.Turn_Off(); nodbtn.Turn_On(); strcpy (Session.Handle, namebuf); transmit = true; break; #else //OLDWAY case (BUTTON_HOUSE | KN_BUTTON): Session.House = HousesType(housebtn.Current_Index()+HOUSE_USSR); strcpy (Session.Handle, namebuf); transmit = true; //display = REDRAW_BACKGROUND; break; #endif //OLDWAY /*------------------------------------------------------------------ User edits the name value; retransmit ------------------------------------------------------------------*/ case (BUTTON_NAME | KN_BUTTON): if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } strcpy (Session.Handle, namebuf); transmit = true; changed = true; break; /*------------------------------------------------------------------ CANCEL: send a SIGN_OFF, bail out with error code ------------------------------------------------------------------*/ case (KN_ESC): case (BUTTON_CANCEL | KN_BUTTON): process = false; rc = false; break; /*------------------------------------------------------------------ Default: manage the inter-player messages ------------------------------------------------------------------*/ default: if (Session.Messages.Manage()) { if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; } /*............................................................... Service keyboard input for any message being edited. ...............................................................*/ i = Session.Messages.Input(input); /*............................................................... If 'Input' returned 1, it means refresh the message display. (We have to redraw the edit line, to erase the cursor.) ...............................................................*/ if (i==1) { Hide_Mouse(); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); Show_Mouse(); } else if (i==2) { /*............................................................... If 'Input' returned 2, it means redraw the message display. Rather than setting 'display', which would redraw all msgs, we only need to erase & redraw the edit box here. ...............................................................*/ Hide_Mouse(); Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); Session.Messages.Draw(); Show_Mouse(); } else if (i==3 || i==4) { /*............................................................... If 'input' returned 3, it means send the current message. ...............................................................*/ memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_MESSAGE; strcpy (SendPacket.Name, namebuf); SendPacket.ID = Session.ColorIdx; if (i==3) { strcpy (SendPacket.Message.Message, Session.Messages.Get_Edit_Buf()); } else { strcpy (SendPacket.Message.Message, Session.Messages.Get_Overflow_Buf()); Session.Messages.Clear_Overflow_Buf(); } /*.................................................................. Send the message ..................................................................*/ NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); NullModem.Service(); /*.................................................................. Add the message to our own screen ..................................................................*/ Session.Messages.Add_Message (SendPacket.Name, SendPacket.ID, SendPacket.Message.Message, (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, -1); Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, TPF_TEXT, NULL, '_', d_message_w); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; } break; } /*--------------------------------------------------------------------- Detect editing of the name buffer, transmit new values to players ---------------------------------------------------------------------*/ if (strcmp (namebuf, Session.Handle)) { strcpy (Session.Handle, namebuf); transmit = true; changed = true; } /*--------------------------------------------------------------------- If our Transmit flag is set, we need to send out a game option packet ---------------------------------------------------------------------*/ if (transmit && (TickCount - transmittime) > PACKET_RETRANS_TIME) { memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_GAME_OPTIONS; strcpy (SendPacket.Name, namebuf); SendPacket.ScenarioInfo.CheatCheck = RuleINI.Get_Unique_ID(); SendPacket.ScenarioInfo.MinVersion = VerNum.Min_Version(); SendPacket.ScenarioInfo.MaxVersion = VerNum.Max_Version(); SendPacket.ScenarioInfo.House = Session.House; SendPacket.ScenarioInfo.Color = Session.ColorIdx; SendPacket.ID = Session.ModemType; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); transmittime = TickCount; transmit = false; //.................................................................. // Keep the player list up to date //.................................................................. if (playerlist.Count()) { item = (char *)playerlist.Get_Item(0); #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); #endif //OLDWAY playerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]; playerlist.Flag_To_Redraw(); } //.................................................................. // Play a little sound effect //.................................................................. Sound_Effect(VOC_OPTIONS_CHANGED); } // // send a timing packet if enough time has gone by. // if ((TickCount - timingtime) > PACKET_TIMING_TIMEOUT) { memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_TIMING; SendPacket.ScenarioInfo.ResponseTime = NullModem.Response_Time(); SendPacket.ID = Session.ModemType; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 0); timingtime = TickCount; } /*--------------------------------------------------------------------- Check for an incoming message ---------------------------------------------------------------------*/ if (NullModem.Get_Message(&ReceivePacket, &packetlen) > 0) { lastmsgtime = TickCount; 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 == Session.ModemType) { WWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING); // to skip the other system not responding msg lastmsgtime = TickCount; 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 - lastredrawtime) > PACKET_REDRAW_TIME) { lastredrawtime = TickCount; oppscorescreen = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; parms_received = true; } } 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; while ( (TickCount - starttime) < 60) NullModem.Service(); WWMessageBox().Process(TXT_USER_SIGNED_OFF); // to skip the other system not responding msg lastmsgtime = TickCount; 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; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; parms_received = true; strcpy (TheirName, ReceivePacket.Name); TheirColor = ReceivePacket.ScenarioInfo.Color; TheirHouse = ReceivePacket.ScenarioInfo.House; /*............................................................... Make sure I don't have the same color as the other guy. ...............................................................*/ if (Session.ColorIdx == TheirColor) { // force transmitting of game options packet transmit = true; transmittime = 0; Session.ColorIdx = (PlayerColorType)(TheirColor + 1); if (Session.ColorIdx >= 6) { Session.ColorIdx = PCOLOR_FIRST; } name_edt.Set_Color(&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); name_edt.Flag_To_Redraw(); if (display < REDRAW_COLORS) display = REDRAW_COLORS; if (housebtn.IsDropped) { housebtn.Collapse(); display = REDRAW_BACKGROUND; } } /*............................................................... Save scenario settings. ...............................................................*/ Session.Options.Credits = ReceivePacket.ScenarioInfo.Credits; Session.Options.Bases = ReceivePacket.ScenarioInfo.IsBases; Session.Options.Tiberium = ReceivePacket.ScenarioInfo.IsTiberium; Session.Options.Goodies = ReceivePacket.ScenarioInfo.IsGoodies; Session.Options.AIPlayers = ReceivePacket.ScenarioInfo.AIPlayers; BuildLevel = ReceivePacket.ScenarioInfo.BuildLevel; Session.Options.UnitCount = ReceivePacket.ScenarioInfo.UnitCount; Seed = ReceivePacket.ScenarioInfo.Seed; Special = ReceivePacket.ScenarioInfo.Special; Options.GameSpeed = ReceivePacket.ScenarioInfo.GameSpeed; if (Session.Options.Tiberium) { Special.IsTGrowth = true; Rule.IsTGrowth = true; Special.IsTSpread = true; Rule.IsTSpread = true; } else { Special.IsTGrowth = false; Rule.IsTGrowth = false; Special.IsTSpread = false; Rule.IsTSpread = false; } //......................................................... // Adjust the gauges //......................................................... countgauge.Set_Maximum( SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); levelgauge.Set_Value(BuildLevel - 1); creditsgauge.Set_Value(Session.Options.Credits); aiplayersgauge.Set_Value(Session.Options.AIPlayers); //......................................................... // Update the options list box //......................................................... optionlist.Check_Item(0, Session.Options.Bases); optionlist.Check_Item(1, Session.Options.Tiberium); optionlist.Check_Item(2, Session.Options.Goodies); optionlist.Check_Item(3, Special.IsCaptureTheFlag); optionlist.Check_Item(4, Special.IsShadowGrow); optionlist.Flag_To_Redraw(); /* ** If the scenario name changed then we need to redraw the whole lot. */ if (strcmp (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario)) { if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND; } /*............................................................... Copy the information about the scenario that the host wants to play so ee can request this scenario from the host if we don't have it locally. ...............................................................*/ strcpy (Session.Options.ScenarioDescription, ReceivePacket.ScenarioInfo.Scenario); strcpy (Session.ScenarioFileName, ReceivePacket.ScenarioInfo.ShortFileName); #ifdef WOLAPI_INTEGRATION strncpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest, sizeof( ReceivePacket.ScenarioInfo.FileDigest )); #else strcpy (Session.ScenarioDigest, (char*)ReceivePacket.ScenarioInfo.FileDigest); #endif Session.ScenarioIsOfficial = ReceivePacket.ScenarioInfo.OfficialScenario; Session.ScenarioFileLength = ReceivePacket.ScenarioInfo.FileLength; //......................................................... // "Clip" the other system's version range to our own // ........................................................ version = VerNum.Clip_Version(ReceivePacket.ScenarioInfo.MinVersion, ReceivePacket.ScenarioInfo.MaxVersion); // ........................................................ // If the greatest-common-version comes back 0, the other // system's range is too low for ours // ........................................................ if (version == 0) { WWMessageBox().Process (TXT_DESTGAME_OUTDATED); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } else if (version == 0xffffffff) { // ........................................................ // If the greatest-common-version comes back 0xffffffff, // the other system's range is too high for ours // ........................................................ WWMessageBox().Process (TXT_YOURGAME_OUTDATED); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } // ........................................................ // Otherwise, 'version' is the highest version we have in // common; look up the protocol that goes with this version. // ........................................................ else { if (ReceivePacket.ScenarioInfo.CheatCheck != RuleINI.Get_Unique_ID()) { WWMessageBox().Process(TXT_MISMATCH); // to skip the other system not responding msg lastmsgtime = TickCount; process = false; rc = false; } else { Session.CommProtocol = VerNum.Version_Protocol(version); #ifndef FIXIT_VERSION_3 PlayingAgainstVersion = version; #endif } } /*......................................................... If this is the first game-options packet we've received, init the game & player lists, then transmit our options to him. .........................................................*/ if (first) { //...................................................... // Add a string to the game list, and two to the player // list //...................................................... item = new char [MPLAYER_NAME_MAX + 64]; gamelist.Add_Item(item); item = new char [MPLAYER_NAME_MAX + 64]; //Need room to display country name playerlist.Add_Item(item, &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]); item = new char [MPLAYER_NAME_MAX + 64]; //Need room to display country name playerlist.Add_Item(item, &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor]); first = false; transmit = true; transmittime = 0; } //......................................................... // Ensure the game list & player list have the latest, // greatest copy of our names & colors. Do this every time // we receive an options packet. //......................................................... item = (char *)gamelist.Get_Item(0); sprintf(item,Text_String(TXT_THATGUYS_GAME), TheirName); item = (char *)playerlist.Get_Item(0); #ifdef OLDWAY if (Session.House==HOUSE_GOOD) { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); #endif //OLDWAY playerlist.Colors[0] = &ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx]; item = (char *)playerlist.Get_Item(1); #ifdef OLDWAY if (TheirHouse==HOUSE_GOOD) { sprintf(item,"%s\t%s",TheirName, Text_String(TXT_ALLIES)); } else { sprintf(item,"%s\t%s",TheirName, Text_String(TXT_SOVIET)); } #else //OLDWAY sprintf (item, "%s\t%s", TheirName, Text_String(HouseTypeClass::As_Reference(TheirHouse).Full_Name())); #endif //OLDWAY playerlist.Colors[1] = &ColorRemaps[(TheirColor == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : TheirColor]; gamelist.Flag_To_Redraw(); playerlist.Flag_To_Redraw(); //......................................................... // Play a little sound effect //......................................................... Sound_Effect(VOC_OPTIONS_CHANGED); break; /*.................................................................. GO: Exit this routine with a success code. ..................................................................*/ case (SERIAL_LOADGAME): load_game = true; case (SERIAL_GO): ready_packet_was_sent = false; if (!load_game){ /* ** Special new kludge for counterstrike. ** ** Find local scenario will fail to match a counterstrike mission ** unless the CS CD is in the drive. So.... ** ** If Counterstrike is installed and this is an official map and ** the file name matches a counterstrike map then tell the host ** that I have the scenario so he can continue while we make ** sure the local user has the Counterstrike CD in the drive. ** */ // This is duplicated for Aftermath scenarios. ajw #ifdef FIXIT_CSII // checked - ajw 9/28/98 if (Session.ScenarioIsOfficial && ( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) || (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) { #else if ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) { #endif CCFileClass check_file ( Session.ScenarioFileName ); if ( !check_file.Is_Available() ) { int current_drive = CCFileClass::Get_CD_Drive(); #ifdef FIXIT_CSII // checked - ajw 9/28/98 int index = Get_CD_Index(current_drive, 1*60); bool needcd = false; if (Is_Mission_Counterstrike(Session.ScenarioFileName)) { if (index != 2 && index != 3) { RequiredCD = 2; needcd = true; } } if (Is_Mission_Aftermath(Session.ScenarioFileName)) { if (index != 3) { RequiredCD = 3; needcd = true; } } if (needcd) { #else if ( Get_CD_Index(current_drive, 1*60) != 2 ){ RequiredCD = 2; #endif #ifdef WIN32 WWDebugString ("RA95 - Counterstrike CD is not in drive\n"); #endif /* ** We should have the scenario but the wrong disk is in. ** Tell the host that I am ready to go anyway. */ memset ((void*)&SendPacket, 0, sizeof (SendPacket)); SendPacket.Command = SERIAL_READY_TO_GO; NullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1); starttime = TickCount; while ( ( NullModem.Num_Send() && ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) ) || ((TickCount - starttime) < 60) ) { NullModem.Service(); } ready_packet_was_sent = true; if (!Force_CD_Available (RequiredCD)){ Emergency_Exit(EXIT_FAILURE); } /* ** Update the internal list of scenarios to include the counterstrike ** list. */ Session.Read_Scenario_Descriptions(); /* ** Make sure we dont time out because of the disk swap */ lastmsgtime = TickCount; } } } /* ** If the scenario that the host wants to play doesnt exist locally then we ** need to request that it is sent. If we can identify the scenario locally then ** we need to fix up the file name so we load the right one. */ if (Find_Local_Scenario (Session.Options.ScenarioDescription, Session.ScenarioFileName, Session.ScenarioFileLength, Session.ScenarioDigest, Session.ScenarioIsOfficial)) { /* ** We have the scenario. Tell the host that I am ready to go. */ if (!ready_packet_was_sent) { memset ((void*)&SendPacket, 0, sizeof (SendPacket)); SendPacket.Command = SERIAL_READY_TO_GO; NullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1); starttime = TickCount; while ( ( NullModem.Num_Send() && ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) ) || ((TickCount - starttime) < 60) ) { NullModem.Service(); } } } else { #ifndef FIXIT_VERSION_3 // Removed restriction on downloading official maps. /* ** Oh dear. Thats a scenario I dont have. Request that the host sends the ** scenario to me provided it isnt an official Westwood scenario. ** ** If the file is received OK then we will get a true return value and the ** actual file name to load will be in Session.ScenarioFileName */ if (Session.ScenarioIsOfficial) { /* ** We dont have the scenario and we dont want to request that it gets ** sent because its an official one. ** Print up a message saying we cant play this scenario and reply to the ** host, telling him to select another. */ memset ((void*)&SendPacket, 0, sizeof (SendPacket)); SendPacket.Command = SERIAL_NO_SCENARIO; NullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1); NullModem.Service(); WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH); display = REDRAW_ALL; lastmsgtime = TickCount; break; } else { #endif #ifdef FIXIT_VERSION_3 if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) ) break; #endif if (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 0)) { rc = false; break; } else { /* ** Make sure we dont time-out because of the download */ lastmsgtime = TickCount; } #ifndef FIXIT_VERSION_3 } #endif } }else{ /* ** Make sure we respond to the host in a load game */ memset ((void*)&SendPacket, 0, sizeof (SendPacket)); SendPacket.Command = SERIAL_READY_TO_GO; NullModem.Send_Message (&SendPacket, sizeof (SendPacket), 1); starttime = TickCount; while ( ( NullModem.Num_Send() && ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) ) || ((TickCount - starttime) < 60) ) { NullModem.Service(); } } /* ** Fall through here... */ strcpy (Scen.ScenarioName, Session.ScenarioFileName); // // calculated one way delay for a packet and overall delay // to execute a packet // if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) { Session.MaxAhead = max( ((((ReceivePacket.ScenarioInfo.ResponseTime / 8) + (Session.FrameSendRate - 1)) / Session.FrameSendRate) * Session.FrameSendRate), (Session.FrameSendRate * 2) ); } else { Session.MaxAhead = max( (ReceivePacket.ScenarioInfo.ResponseTime / 8), MODEM_MIN_MAX_AHEAD ); } process = false; rc = true; if (ReceivePacket.Command == SERIAL_LOADGAME) load_game = true; break; /*.................................................................. Incoming message: add to our list ..................................................................*/ case (SERIAL_MESSAGE): oppscorescreen = false; Session.Messages.Add_Message (ReceivePacket.Name, ((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID, ReceivePacket.Message.Message, ((PlayerColorType)ReceivePacket.ID == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : (PlayerColorType)ReceivePacket.ID, TPF_TEXT, -1); Sound_Effect(VOC_INCOMING_MESSAGE); if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; break; // // throw away timing packet // case (SERIAL_TIMING): oppscorescreen = false; break; // // print msg waiting for opponent // case (SERIAL_SCORE_SCREEN): oppscorescreen = true; if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; parms_received = true; break; default: break; } } } // if we haven't received a msg for 10 seconds exit if ((TickCount - lastmsgtime) > msg_timeout) { WWMessageBox().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(); } /*------------------------------------------------------------------------ Prepare to load the scenario ------------------------------------------------------------------------*/ if (rc) { Session.NumPlayers = 2; /*..................................................................... Add both players to the Players vector; the local system is always index 0. .....................................................................*/ who = new NodeNameType; #ifdef FIXIT_MODEM_LOAD_CRASH /* If the names of the players are the same then we MUST force them * be be unique. This is necessary to prevent a crash after loading * a modem save game. */ if (strcmp(TheirName, namebuf) == 0) { if (strlen(TheirName) == (MPLAYER_NAME_MAX - 1)) { namebuf[MPLAYER_NAME_MAX - 1] = '\0'; } else { strcat(namebuf, "2"); } } #endif strcpy(who->Name, namebuf); who->Player.House = Session.House; who->Player.Color = Session.ColorIdx; who->Player.ProcessTime = -1; Session.Players.Add (who); who = new NodeNameType; strcpy(who->Name, TheirName); who->Player.House = TheirHouse; who->Player.Color = TheirColor; who->Player.ProcessTime = -1; Session.Players.Add (who); starttime = TickCount; while ( ( NullModem.Num_Send() && ((TickCount - starttime) < PACKET_SENDING_TIMEOUT) ) || ((TickCount - starttime) < 60) ) { #if(SHOW_MONO) NullModem.Mono_Debug_Print(0); #endif NullModem.Service(); } // clear queue to keep from doing any resends NullModem.Init_Send_Queue(); } else { if ( !recsignedoff ) { /*..................................................................... Broadcast my sign-off over my network .....................................................................*/ memset (&SendPacket, 0, sizeof(SerialPacketType)); SendPacket.Command = SERIAL_SIGN_OFF; SendPacket.ScenarioInfo.Color = Session.ColorIdx; // use Color for ID SendPacket.ID = Session.ModemType; NullModem.Send_Message (&SendPacket, sizeof(SendPacket), 1); starttime = TickCount; while ( (NullModem.Num_Send() && ((TickCount - starttime) < PACKET_CANCEL_TIMEOUT) ) || ((TickCount - 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 == Session.ModemType) { // exit while break; } } NullModem.Service(); } } Shutdown_Modem(); } /*------------------------------------------------------------------------ Clean up the list boxes ------------------------------------------------------------------------*/ // while (optionlist.Count()>0) { // item = (char *)optionlist.Get_Item(0); // delete [] item; // optionlist.Remove_Item(item); // } while (gamelist.Count()>0) { item = (char *)gamelist.Get_Item(0); delete [] item; gamelist.Remove_Item(item); } while (playerlist.Count()>0) { item = (char *)playerlist.Get_Item(0); delete [] item; playerlist.Remove_Item(item); } /*------------------------------------------------------------------------ Remove the chat edit box ------------------------------------------------------------------------*/ Session.Messages.Remove_Edit(); /*------------------------------------------------------------------------ Restore screen ------------------------------------------------------------------------*/ Hide_Mouse(); Load_Title_Page(true); //#ifdef WIN32 // Load_Uncompress(CCFileClass("TITLE.CPS"), SysMemPage, SysMemPage, CCPalette); // SysMemPage.Scale(SeenPage); //#else // Load_Uncompress(CCFileClass("TITLE.CPS"), HidPage, HidPage, CCPalette); // HidPage.Blit(SeenPage); //#endif Show_Mouse(); /*------------------------------------------------------------------------ Save any changes made to our options ------------------------------------------------------------------------*/ if (changed) { Session.Write_MultiPlayer_Settings (); } if (load_game) { if (!Load_Game (-1)) { WWMessageBox().Process (TXT_ERROR_LOADING_GAME); rc = false; } Frame++; } 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) { /*........................................................................ Dialog & button dimensions ........................................................................*/ int d_dialog_w = 280 * RESFACTOR; // dialog width int d_dialog_h = 160 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = ((200 * RESFACTOR - 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 = 7 * RESFACTOR; // ht of 6-pt text int d_margin = 7 * RESFACTOR; // margin width/height int d_phonelist_w = 248 * RESFACTOR; int d_phonelist_h = 87 * RESFACTOR; int d_phonelist_x = d_dialog_cx - (d_phonelist_w / 2); int d_phonelist_y = d_dialog_y + d_margin + d_txt6_h + 11 * RESFACTOR; int d_add_w = 45 * RESFACTOR; int d_add_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_edit_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_delete_h = 9 * RESFACTOR; 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) * RESFACTOR + 3 * RESFACTOR; int d_numedit_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_dial_h = 9 * RESFACTOR; 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 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; 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*RESFACTOR, 207*RESFACTOR}; // tabs for list box char *item; // for removing items from list box PhoneEntryClass *p_entry; // for creating / editing phonebook entries bool changed = false; // 1 = save changes to INI file bool firsttime = false; /*........................................................................ Buttons ........................................................................*/ GadgetClass *commands; // button list ListClass phonelist(BUTTON_PHONELIST, d_phonelist_x, d_phonelist_y, d_phonelist_w, d_phonelist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); TextButtonClass addbtn(BUTTON_ADD, TXT_ADD, TPF_BUTTON, d_add_x, d_add_y, d_add_w, d_add_h); TextButtonClass editbtn(BUTTON_EDIT, TXT_EDIT, TPF_BUTTON, d_edit_x, d_edit_y, d_edit_w, d_edit_h); TextButtonClass deletebtn(BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w, d_delete_h); TextButtonClass dialbtn(BUTTON_DIAL, TXT_DIAL, TPF_BUTTON, d_dial_x, d_dial_y, d_dial_w, d_dial_h); TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); EditClass numedit (BUTTON_NUMEDIT, phone_num, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, 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 (Session.CurPhoneIdx == -1) { firsttime = true; } /* ---------------------------- Processing loop ----------------------------- */ while (process) { /* ........................ Invoke game callback ......................... */ Call_Back(); #ifdef WIN32 /* ** 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; } #endif /* ...................... Refresh display if needed ...................... */ if (display) { Hide_Mouse(); /* .................. Redraw backgound & dialog box ................... */ if (display >= REDRAW_BACKGROUND) { Load_Title_Page(true); CCPalette.Set(); 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_TEXT); /*............................................................... Dialog & Field labels ...............................................................*/ Draw_Caption (TXT_PHONE_LIST, d_dialog_x, d_dialog_y, d_dialog_w); phonelist.Draw_Me (true); } /* .......................... Redraw buttons .......................... */ if (display >= REDRAW_BUTTONS) { 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 = false; } /* ---------------------------- 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. ...............................................................*/ #ifdef FIXIT_PHONELIST_CRASH if (Session.CurPhoneIdx != -1) { #endif if (phonelist.Current_Index() != Session.CurPhoneIdx) { Session.CurPhoneIdx = phonelist.Current_Index(); strcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number); numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM ); changed = true; } #ifdef FIXIT_PHONELIST_CRASH } #endif 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 ) ) { Session.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 < Session.PhoneBook.Count(); i++) { if (p_entry == Session.PhoneBook[i]) { Session.CurPhoneIdx = i; strcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number); numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM ); phonelist.Set_Selected_Index( Session.CurPhoneIdx ); } } changed = true; } 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 (Session.CurPhoneIdx==-1) break; /*............................................................... Allocate a new entry & copy the currently-selected entry into it ...............................................................*/ p_entry = new PhoneEntryClass(); (*p_entry) = (*Session.PhoneBook[Session.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 ) ) { (*Session.PhoneBook[Session.CurPhoneIdx]) = (*p_entry); Build_Phone_Listbox(&phonelist, &numedit, phone_num); /*............................................................ Set the current listbox index to the newly-added item. ............................................................*/ for (i = 0; i < Session.PhoneBook.Count(); i++) { if (Session.PhoneBook[Session.CurPhoneIdx] == Session.PhoneBook[i]) { Session.CurPhoneIdx = i; strcpy (phone_num, Session.PhoneBook[Session.CurPhoneIdx]->Number); numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM ); phonelist.Set_Selected_Index( Session.CurPhoneIdx ); } } changed = true; } delete p_entry; display = REDRAW_ALL; break; /*------------------------------------------------------------------ Delete the current entry ------------------------------------------------------------------*/ case (BUTTON_DELETE | KN_BUTTON): /*............................................................... Do nothing if no entry is selected. ...............................................................*/ if (Session.CurPhoneIdx == -1) break; /*............................................................... Delete the current item & rebuild the phone listbox ...............................................................*/ Session.PhoneBook.Delete (Session.CurPhoneIdx); Build_Phone_Listbox(&phonelist, &numedit, phone_num); if (Session.CurPhoneIdx == -1) { *phone_num = 0; numedit.Set_Text (phone_num, PhoneEntryClass::PHONE_MAX_NUM ); } changed = true; 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 (Session.CurPhoneIdx == -1 || strcmp( Session.PhoneBook[Session.CurPhoneIdx]->Number, phone_num) ) { if ( strlen(phone_num) == 0) { // do not dial dialbtn.IsPressed = true; 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; Session.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 < Session.PhoneBook.Count(); i++) { if (p_entry == Session.PhoneBook[i]) { Session.CurPhoneIdx = i; } } changed = true; } 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) { Session.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 *)(&Session.PhoneBook[0]), Session.PhoneBook.Count(), sizeof(class PhoneEntryClass *), Phone_Compare); /*........................................................................ Build the list ........................................................................*/ for (i = 0; i < Session.PhoneBook.Count(); i++) { item = new char[80]; if ( !(strlen( Session.PhoneBook[i]->Name )) ) { strcpy( phonename, " " ); } else { strncpy( phonename, Session.PhoneBook[i]->Name, 20 ); phonename[21] = 0; } if ( !(strlen( Session.PhoneBook[i]->Number )) ) { strcpy( phonenum, " " ); } else { if ( strlen( Session.PhoneBook[i]->Number ) < 14) { strcpy( phonenum, Session.PhoneBook[i]->Number ); } else { strncpy( phonenum, Session.PhoneBook[i]->Number, 12 ); phonenum[12] = 0; strcat( phonenum, "..." ); } } if (Session.PhoneBook[i]->Settings.Baud != -1) { sprintf(item,"%s\t%s\t%d", phonename, phonenum, Session.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 || Session.CurPhoneIdx < -1) { Session.CurPhoneIdx = -1; } else { if (Session.CurPhoneIdx >= list->Count() ) { Session.CurPhoneIdx = 0; } } /*........................................................................ Fill in phone number edit buffer ........................................................................*/ if (Session.CurPhoneIdx > -1) { strcpy (buf, Session.PhoneBook[Session.CurPhoneIdx]->Number); edit->Set_Text (buf, PhoneEntryClass::PHONE_MAX_NUM ); list->Set_Selected_Index( Session.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) { /*........................................................................ Dialog & button dimensions ........................................................................*/ int d_dialog_w = 230 * RESFACTOR; // dialog width int d_dialog_h = 110 * RESFACTOR; // dialog height int d_dialog_x = ((320 * RESFACTOR - d_dialog_w) / 2); // dialog x-coord int d_dialog_y = ((136 * RESFACTOR - 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 = 7 * RESFACTOR; // ht of 6-pt text int d_margin = 7 * RESFACTOR; // margin width/height int d_name_w = ( (PhoneEntryClass::PHONE_MAX_NAME - 1) * 6) * RESFACTOR + 3 * RESFACTOR; int d_name_h = 9 * RESFACTOR; int d_name_x = d_dialog_x + (((d_dialog_w - d_name_w) * 3) / 4) - 5 * RESFACTOR; int d_name_y = d_dialog_y + 25 * RESFACTOR; int d_number_w = ( (PhoneEntryClass::PHONE_MAX_NUM - 1) * 6) * RESFACTOR + 3 * RESFACTOR; int d_number_h = 9 * RESFACTOR; int d_number_x = d_dialog_x + (((d_dialog_w - d_number_w) * 3) / 4) - 5 * RESFACTOR; int d_number_y = d_name_y + d_name_h + d_margin; int d_default_w = 130 * RESFACTOR; int d_default_h = 9 * RESFACTOR; int d_default_x = d_dialog_cx - (d_default_w / 2); int d_default_y = d_number_y + d_number_h + d_margin; int d_custom_w = 130 * RESFACTOR; int d_custom_h = 9 * RESFACTOR; int d_custom_x = d_dialog_cx - (d_default_w / 2); int d_custom_y = d_default_y + d_default_h + d_margin; int d_save_w = 55 * RESFACTOR; int d_save_h = 9 * RESFACTOR; 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 - 5*RESFACTOR; int d_cancel_w = 55 * RESFACTOR; int d_cancel_h = 9 * RESFACTOR; int d_cancel_x = d_dialog_cx + d_margin; int d_cancel_y = d_dialog_y + d_dialog_h - d_margin - d_cancel_h - 5*RESFACTOR; /*........................................................................ 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 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; bool custom = false; bool firsttime = true; RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); /*........................................................................ Buttons ........................................................................*/ GadgetClass *commands; // button list EditClass nameedit(BUTTON_NAME, namebuf, PhoneEntryClass::PHONE_MAX_NAME, TPF_TEXT, d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC); EditClass numedit(BUTTON_NUMBER, numbuf, PhoneEntryClass::PHONE_MAX_NUM, TPF_TEXT, d_number_x, d_number_y, d_number_w, d_number_h, EditClass::ALPHANUMERIC); TextButtonClass defaultbtn(BUTTON_DEFAULT, TXT_DEFAULT_SETTINGS, TPF_BUTTON, d_default_x, d_default_y, d_default_w, d_default_h); TextButtonClass custombtn(BUTTON_CUSTOM, TXT_CUSTOM_SETTINGS, TPF_BUTTON, d_custom_x, d_custom_y, d_custom_w, d_custom_h); TextButtonClass savebtn(BUTTON_SAVE, TXT_SAVE_BUTTON, TPF_BUTTON, d_save_x, d_save_y, d_save_w, d_save_h); TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 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 = Session.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 ----------------------------- */ bool process = true; // process while true while (process) { /* ........................ Invoke game callback ......................... */ Call_Back(); #ifdef WIN32 /* ** 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; } #endif /* ...................... Refresh display if needed ...................... */ if (display) { Hide_Mouse(); /* .................. Redraw backgound & dialog box ................... */ if (display >= REDRAW_BACKGROUND) { Load_Title_Page(true); CCPalette.Set(); Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); Draw_Caption (TXT_PHONE_LISTING, d_dialog_x, d_dialog_y, d_dialog_w); /*............................................................... Dialog & Field labels ...............................................................*/ Fancy_Text_Print (TXT_NAME_COLON, d_name_x - 5 * RESFACTOR, d_name_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT); Fancy_Text_Print (TXT_NUMBER_COLON, d_number_x - 5 * RESFACTOR, d_number_y + 1 * RESFACTOR, scheme, TBLACK, TPF_RIGHT | TPF_TEXT); } /* .......................... Redraw buttons .......................... */ if (display >= REDRAW_BUTTONS) { commands->Flag_List_To_Redraw(); } Show_Mouse(); display = REDRAW_NONE; } /* ........................... Get user input ............................ */ KeyNumType input = commands->Input(); if ( firsttime ) { nameedit.Set_Focus(); nameedit.Flag_To_Redraw(); input = commands->Input(); firsttime = false; } /* ---------------------------- 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 = false; break; /*------------------------------------------------------------------ Use Custom Serial Settings ------------------------------------------------------------------*/ case (BUTTON_CUSTOM | KN_BUTTON): if (Com_Settings_Dialog (&settings)) { custombtn.Turn_On(); defaultbtn.Turn_Off(); } custom = true; 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. */ Session.ModemService = false; // save for later to reconnect DialSettings = settings; modemstatus = NullModem.Get_Modem_Status(); if (reconnect) { if ( (modemstatus & CD_SET) ) { connected = true; Session.ModemService = true; return( connected ); } } else if ( (modemstatus & CD_SET) ) { NullModem.Hangup_Modem(); Session.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(); //#ifndef WIN32 /* ** 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 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(); WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.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(); WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.ModemService = true; return( connected ); } break; default: WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.ModemService = true; return( connected ); } //#else //WIN32 // Session.ModemService = true; // return( connected ); //#endif //WIN32 } else if ( modemstatus == -1 ) { NullModem.Remove_Modem_Echo(); NullModem.Print_EchoBuf(); NullModem.Reset_EchoBuf(); WWMessageBox().Process( TXT_ERROR_IN_INITSTRING ); // WWMessageBox().Process( "Error in the InitString." ); Session.ModemService = true; return( connected ); } #ifdef WIN32 #ifdef FIXIT_APTIVA_MODEM /* ** Completely disable audio. This is required for MWave devices like those ** found in the IBM Aptiva. */ ThemeType old_theme = THEME_NONE; if (SoundOn){ old_theme = Theme.What_Is_Playing(); Theme.Stop(); CountDownTimerClass wait; Call_Back(); wait.Set (60,true); while ( wait.Time() ) { Call_Back(); } Sound_End(); Call_Back(); wait.Set (60,true); while ( wait.Time() ) { Call_Back(); } SoundOn = 0; } #endif //FIXIT_APTIVA_MODEM #endif //WIN32 dialstatus = NullModem.Dial_Modem( DialString, settings->DialMethod, reconnect ); if (reconnect) { /* --------------------------- Redraw the display --------------------------- */ HidPage.Clear(); Map.Flag_To_Redraw(true); Map.Render(); } switch ( dialstatus ) { case DIAL_CONNECTED: connected = true; break; case DIAL_NO_CARRIER: WWMessageBox().Process(TXT_NO_CARRIER); connected = false; break; case DIAL_BUSY: WWMessageBox().Process(TXT_LINE_BUSY); connected = false; break; case DIAL_ERROR: WWMessageBox().Process(TXT_NUMBER_INVALID); connected = false; break; case DIAL_NO_DIAL_TONE: WWMessageBox().Process(TXT_NO_DIAL_TONE); connected = false; break; case DIAL_CANCELED: NullModem.Hangup_Modem(); Session.ModemService = false; WWMessageBox().Process(TXT_DIALING_CANCELED); connected = false; break; } NullModem.Remove_Modem_Echo(); NullModem.Print_EchoBuf(); NullModem.Reset_EchoBuf(); #ifdef WIN32 #ifdef FIXIT_APTIVA_MODEM /* ** Restore audio capability */ SoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 ); if (SoundOn){ Theme.Play_Song (old_theme); } #endif //FIXIT_APTIVA_MODEM #endif //WIN32 Session.ModemService = true; return( connected ); } /* end of Dial_Modem */ static bool Answer_Modem( SerialSettingsType *settings, bool reconnect ) { bool connected = false; DialStatusType dialstatus; int modemstatus; /* ** Turn modem servicing off in the callback routine. */ Session.ModemService = false; // save for later to reconnect DialSettings = settings; modemstatus = NullModem.Get_Modem_Status(); if (reconnect) { if ( (modemstatus & CD_SET) ) { connected = true; Session.ModemService = true; return( connected ); } } else if ( (modemstatus & CD_SET) ) { NullModem.Hangup_Modem(); Session.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(); //#ifndef WIN32 /* ** 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 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(); WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.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(); WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.ModemService = true; return( connected ); } break; default: WWMessageBox().Process( TXT_UNABLE_FIND_MODEM ); Session.ModemService = true; return( connected ); } //#else //WIN32 // Session.ModemService = true; // return( connected ); //#endif //WIN32 } else if ( modemstatus == -1 ) { NullModem.Remove_Modem_Echo(); NullModem.Print_EchoBuf(); NullModem.Reset_EchoBuf(); WWMessageBox().Process( TXT_ERROR_IN_INITSTRING ); Session.ModemService = true; return( connected ); } #ifdef WIN32 #ifdef FIXIT_APTIVA_MODEM /* ** Completely disable audio. This is required for some MWave devices like those ** found in the IBM Aptiva. */ ThemeType old_theme = THEME_NONE; if (SoundOn){ old_theme = Theme.What_Is_Playing(); Theme.Stop(); CountDownTimerClass wait; Call_Back(); wait.Set (60,true); while ( wait.Time() ) { Call_Back(); } Sound_End(); Call_Back(); wait.Set (60,true); while ( wait.Time() ) { Call_Back(); } SoundOn = 0; } #endif //FIXIT_APTIVA_MODEM #endif //WIN32 dialstatus = NullModem.Answer_Modem( reconnect ); switch ( dialstatus ) { case DIAL_CONNECTED: connected = true; break; case DIAL_NO_CARRIER: WWMessageBox().Process(TXT_NO_CARRIER); connected = false; break; // case DIAL_BUSY: // WWMessageBox().Process(TXT_LINE_BUSY); // connected = false; // break; case DIAL_ERROR: WWMessageBox().Process(TXT_NUMBER_INVALID); connected = false; break; case DIAL_CANCELED: WWMessageBox().Process(TXT_ANSWERING_CANCELED); connected = false; break; } NullModem.Remove_Modem_Echo(); NullModem.Print_EchoBuf(); NullModem.Reset_EchoBuf(); #ifdef WIN32 #ifdef FIXIT_APTIVA_MODEM /* ** Restore audio capability */ SoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 ); if (SoundOn){ Theme.Play_Song (old_theme); } #endif //FIXIT_APTIVA_MODEM #endif //WIN32 Session.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++; } } /* 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 (MonoClass::Is_Enabled()) { Mono_Printf("%s",buf); } else { printf("%s",buf); } } else { if (Debug_Heap_Dump) { printf("%s",buf); } if (Debug_Modem_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 */ } void Log_Start_Time( char *string ) { // LogDump_Print = true; LogLevel = 0; LogLevelTime[ LogLevel ] = LogLastTime = TickCount; Smart_Printf( "start tick=%d, %s \n", LogLastTime, string ); } void Log_End_Time( char *string ) { int i; unsigned long currtime; unsigned long ticks; currtime = TickCount; while (LogLevel >= 0) { if (LogLevel < MAX_LOG_LEVEL) { // // put one space for each level as indenting // i = 0; while (i++ < LogLevel) { Smart_Printf( " " ); } } else { Smart_Printf( "LogLevel %d too large!-! \n", LogLevel); LogLevel = MAX_LOG_LEVEL - 1; } ticks = currtime - LogLevelTime[ LogLevel-- ]; Smart_Printf( "end tick=%d, ticks=%d, tsecs=%d, %s \n", currtime, ticks, ((ticks * 10) / 60), string ); } LogDump_Print = false; } void Log_Time( char *string ) { int i; unsigned long currtime; unsigned long ticks; currtime = TickCount; if (LogLevel < MAX_LOG_LEVEL) { // // put one space for each level as indenting // i = 0; while (i++ < LogLevel) { Smart_Printf( " " ); } } else { Smart_Printf( "LogLevel %d too large!-! \n", LogLevel); LogLevel = MAX_LOG_LEVEL - 1; } ticks = currtime - LogLastTime; Smart_Printf( "tick=%d, ticks=%d, tsecs=%d, %s \n", currtime, ticks, ((ticks * 10) / 60), string ); LogLastTime = currtime; } void Log_Start_Nest_Time( char *string ) { int i; unsigned long currtime; unsigned long ticks; currtime = TickCount; if (LogLevel < MAX_LOG_LEVEL) { // // put one space for each level as indenting // i = 0; while (i++ < LogLevel) { Smart_Printf( " " ); } } else { Smart_Printf( "LogLevel %d too large!-! \n", LogLevel); LogLevel = MAX_LOG_LEVEL - 1; } ticks = currtime - LogLastTime; Smart_Printf( "start ntick=%d, ticks=%d, tsecs=%d, %s \n", currtime, ticks, ((ticks * 10) / 60), string ); if (LogLevel >= (MAX_LOG_LEVEL - 1) ) { Smart_Printf( "Could not start another nesting Maxed at %d,%d!-! \n", LogLevel, (MAX_LOG_LEVEL - 1) ); } else { LogLevelTime[ ++LogLevel ] = currtime; } LogLastTime = currtime; } void Log_End_Nest_Time( char *string ) { int i; unsigned long currtime; unsigned long ticks; currtime = TickCount; if (LogLevel <= 0) { Smart_Printf( "Could not end another nesting Mined at %d,%d!-! \n", LogLevel, 0 ); LogLevel = 0; } if (LogLevel < MAX_LOG_LEVEL) { // // put one space for each level as indenting // i = 0; while (i++ < LogLevel) { Smart_Printf( " " ); } } else { Smart_Printf( "LogLevel %d too large!-! \n", LogLevel); LogLevel = MAX_LOG_LEVEL - 1; } ticks = currtime - LogLevelTime[ LogLevel ]; Smart_Printf( "end ntick=%d, ticks=%d, secs=%d, %s \n", currtime, ticks, ((ticks * 10) / 60), string ); if (LogLevel) { LogLevel--; } LogLastTime = currtime; } #endif