CnC_Remastered_Collection

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

WOL_LOGN.CPP (18740B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 #ifdef WOLAPI_INTEGRATION
     17 
     18 //	Wol_Logn.cpp - WW online name/password dialog.
     19 //	ajw 07/16/98
     20 
     21 #include "function.h"
     22 
     23 #include "IconList.h"
     24 #include "WolapiOb.h"
     25 #include "PassEdit.h"
     26 #include "WolStrng.h"
     27 #include "BigCheck.h"
     28 
     29 bool ReadSavedNicks( WolapiObject* pWO, IconListClass& NickList, char* szNameBuffer, char* szPassBuffer );
     30 bool bSaveNick( WolapiObject* pWO, const char* szNickToSave, const char* szPassToSave, bool bPassIsMangled );
     31 void DeleteNick( WolapiObject* pWO, int iOneBasedEntryToDelete );
     32 //char* LoadShpFile( const char* szShpFile );
     33 
     34 void DebugChatDef( HRESULT hRes );
     35 
     36 extern bool bTabKeyPressedHack;
     37 
     38 //#include "WolDebug.h"
     39 
     40 //***********************************************************************************************
     41 int WOL_Login_Dialog( WolapiObject* pWO )
     42 {
     43 	//	Return values: 0 = user cancels, 1 = success, -1 = force game exit
     44 
     45 	if( pWO->bLoggedIn() )
     46 	{
     47 		pWO->bReturningAfterGame = true;	//	Set trigger for chat dialog.
     48 		return 1;		//	We are already logged in, and have just come back from a game.
     49 	}
     50 
     51 	/*
     52 	**	Dialog & button dimensions
     53 	*/
     54 #ifdef FRENCH
     55 	int d_dialog_w = 160 * RESFACTOR;											// dialog width
     56 #else
     57 	int d_dialog_w = 150 * RESFACTOR;											// dialog width
     58 #endif
     59 	int d_dialog_h = 85 * RESFACTOR;											// dialog height
     60 	int d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);
     61 	int d_dialog_y = (((255 * RESFACTOR) - d_dialog_h) / 2);
     62 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// coord of x-center
     63 
     64 	int d_txt8_h = 11 * RESFACTOR;												// ht of 8-pt text
     65 	int d_margin = 7 * RESFACTOR;												// margin width/height
     66 	int x_margin = 16 * RESFACTOR;												// margin width/height
     67 
     68 	int top_margin = 0;
     69 
     70 	int d_name_w = 66 * RESFACTOR;
     71 	int d_name_h = 10 * RESFACTOR;
     72 #ifdef FRENCH
     73 	int d_name_x = d_dialog_x + 25 * RESFACTOR;
     74 #else
     75 	int d_name_x = d_dialog_x + 20 * RESFACTOR;
     76 #endif
     77 	int d_name_y = d_dialog_y + top_margin + 25 * RESFACTOR;
     78 
     79 	int d_pass_w = 36 * RESFACTOR;
     80 	int d_pass_h = d_name_h;
     81 	int d_pass_x = d_name_x + d_name_w + 6 * RESFACTOR;
     82 	int d_pass_y = d_name_y;
     83 
     84 	int d_list_w = d_name_w;
     85 	int d_list_h = 20 * RESFACTOR;
     86 	int d_list_x = d_name_x;
     87 	int d_list_y = d_dialog_y + top_margin + 40 * RESFACTOR;
     88 
     89 //	int d_save_w = d_pass_w;
     90 	int d_save_h = 9 * RESFACTOR;
     91 	int d_save_x = d_pass_x + ( d_pass_w / 2 ) - ( d_pass_w / 2 );
     92 	int d_save_y = d_list_y;	// + ( d_list_h / 2 ) - ( d_save_h / 2 );
     93 
     94 	int d_delete_w = d_pass_w;
     95 	int d_delete_h = 10 * RESFACTOR;
     96 	int d_delete_x = d_save_x;
     97 	int d_delete_y = d_list_y + d_list_h - d_delete_h;
     98 
     99 #ifdef FRENCH
    100 	int d_connect_w = 45 * RESFACTOR;
    101 #else
    102 	int d_connect_w = 40 * RESFACTOR;
    103 #endif
    104 	int d_connect_h = 13 * RESFACTOR;
    105 	int d_connect_x = d_name_x + d_name_w/2 - d_connect_w/2;
    106 	int d_connect_y = d_dialog_y + top_margin + 65 * RESFACTOR;	//d_dialog_y + d_dialog_h - d_connect_h - d_margin;
    107 
    108 #if defined(GERMAN) || defined(FRENCH)
    109 	int d_cancel_w = 40 * RESFACTOR;//BG:40
    110 #else
    111 	int d_cancel_w = 40 * RESFACTOR;
    112 #endif
    113 	int d_cancel_h = 13 * RESFACTOR;
    114 	int d_cancel_x = d_pass_x + d_pass_w/2 - d_cancel_w/2;	//d_dialog_cx + d_margin;
    115 	int d_cancel_y = d_connect_y;
    116 
    117 	/*
    118 	**	Button enumerations
    119 	*/
    120 	enum {
    121 		BUTTON_CONNECT = 100,
    122 		BUTTON_CANCEL,
    123 		LISTBOX_NICKS,
    124 		EDITBOX_NAME,
    125 		EDITBOX_PASS,
    126 		BUTTON_SAVECHECK,
    127 		BUTTON_DELETE,
    128 	};
    129 
    130 	/*
    131 	**	Redraw values: in order from "top" to "bottom" layer of the dialog
    132 	*/
    133 	typedef enum {
    134 		REDRAW_NONE = 0,
    135 		REDRAW_BUTTONS,
    136 		REDRAW_BACKGROUND,
    137 		REDRAW_ALL = REDRAW_BACKGROUND
    138 	} RedrawType;
    139 
    140 	/*
    141 	**	Dialog variables
    142 	*/
    143 	int iReturn = 1;		//	0 = user cancels, 1 = success, -1 = force game exit
    144 
    145 	/*
    146 	**	Other Variables
    147 	*/
    148 	char szNameBuffer[ WOL_NAME_LEN_MAX ] = {0};				//	User name.
    149 	char szPassBuffer[ WOL_PASSWORD_LEN ] = {0};				//	User password.
    150 
    151 	/*
    152 	**	Buttons
    153 	*/
    154 	ControlClass* commands = NULL;		// the button list
    155 
    156 	TextButtonClass ConnectBtn( BUTTON_CONNECT, TXT_WOL_CONNECT, TPF_BUTTON, d_connect_x, d_connect_y, d_connect_w );
    157 	TextButtonClass CancelBtn( BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );
    158 
    159 	IconListClass NickList( LISTBOX_NICKS, d_list_x, d_list_y, d_list_w, d_list_h, TPF_6PT_GRAD | TPF_NOSHADOW,
    160 								MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 1, 0 );
    161 
    162 	WOLEditClass NameEdit( EDITBOX_NAME, szNameBuffer, sizeof(szNameBuffer), TPF_6PT_GRAD|TPF_NOSHADOW, 
    163 							d_name_x, d_name_y, d_name_w, -1, EditClass::ALPHANUMERIC );
    164 
    165 	PassEditClass PassEdit( EDITBOX_PASS, szPassBuffer, sizeof(szPassBuffer), TPF_6PT_GRAD|TPF_NOSHADOW, 
    166 							d_pass_x, d_pass_y, d_pass_w, -1, EditClass::ALPHANUMERIC );
    167 
    168 	//	Just making sure globals are set right before String_Pixel_Width() call... sigh
    169 	Fancy_Text_Print( TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD | TPF_NOSHADOW );
    170 	int iSaveTextWidth = String_Pixel_Width( TXT_WOL_SAVELOGIN ) + BIGCHECK_OFFSETX;
    171 	BigCheckBoxClass SaveCheckBox( BUTTON_SAVECHECK, d_save_x, d_save_y, iSaveTextWidth, d_save_h, 
    172 										TXT_WOL_SAVELOGIN, TPF_6PT_GRAD | TPF_NOSHADOW, true );
    173 
    174 	TextButtonClass DeleteBtn( BUTTON_DELETE, TXT_DELETE_BUTTON, TPF_BUTTON, d_delete_x, d_delete_y, d_delete_w );
    175 
    176 	/*
    177 	**	Initialize.
    178 	*/
    179 	Set_Logic_Page(SeenBuff);
    180 
    181 	//	Get saved nickname/passwords from the registry.
    182 	if( ReadSavedNicks( pWO, NickList, szNameBuffer, szPassBuffer ) )
    183 	{
    184 		PassEdit.bClearOnNextSetFocus = true;
    185 	}
    186 	else
    187 	{
    188 		//	Offer user the chance to go to web site now to get a nick.
    189 		if( pWO->DoWebRegistration() )
    190 		{
    191 			//	User chose to go to web page. Leave function so that we'll re-read nicks when they return.
    192 			return 0;
    193 		}
    194 	}
    195 
    196 	/*
    197 	**	Create the button list.
    198 	*/
    199 	commands = &ConnectBtn;
    200 	CancelBtn.Add_Tail(*commands);
    201 	NickList.Add_Tail(*commands);
    202 	NameEdit.Add_Tail(*commands);
    203 	PassEdit.Add_Tail(*commands);
    204 	SaveCheckBox.Add_Tail(*commands);
    205 	DeleteBtn.Add_Tail(*commands);
    206 	NameEdit.Set_Focus();
    207 
    208 	if( NickList.Count() == 0 )
    209 		DeleteBtn.Disable();
    210 
    211 	/*
    212 	**	Main Processing Loop.
    213 	*/
    214 	Keyboard->Clear();
    215 	bool firsttime = true;
    216 	bool display = true;
    217 	bool process = true;
    218 	while (process) {
    219 
    220 		/*
    221 		**	Invoke game callback.
    222 		*/
    223 		Call_Back();
    224 
    225 		#ifdef WIN32
    226 		/*
    227 		** If we have just received input focus again after running in the background then
    228 		** we need to redraw.
    229 		*/
    230 		if (AllSurfaces.SurfacesRestored) {
    231 			AllSurfaces.SurfacesRestored=FALSE;
    232 			display = true;
    233 		}
    234 		#endif
    235 
    236 		/*
    237 		**	Refresh display if needed.
    238 		*/
    239 		if (display) {
    240 
    241 			//------------------------------------------------------------------------
    242 			//	Clear screen
    243 			//------------------------------------------------------------------------
    244 			Hide_Mouse();
    245 			Load_Title_Page(true);
    246 //			Show_Mouse();
    247 
    248 			/*
    249 			**	Display the dialog box.
    250 			*/
    251 //			Hide_Mouse();
    252 			if (display) {
    253 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
    254 				Draw_Caption(TXT_WOL_LOGINDIALOG, d_dialog_x, d_dialog_y, d_dialog_w);
    255 			}
    256 
    257 			/*
    258 			**	Redraw the buttons.
    259 			*/
    260 			if (display) {
    261 				Fancy_Text_Print( TXT_WOL_NAME, d_name_x + ( d_name_w / 2 ), d_name_y - 14,
    262 									GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER );
    263 				Fancy_Text_Print( TXT_WOL_PASSWORD, d_pass_x + ( d_pass_w / 2 ), d_pass_y - 14,
    264 									GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT | TPF_CENTER );
    265 				commands->Flag_List_To_Redraw();
    266 			}
    267 			Show_Mouse();
    268 			display = false;
    269 		}
    270 
    271 		//	Force mouse visible, as some beta testers report unexplicable disappearing cursors.
    272 		while( Get_Mouse_State() )
    273 			Show_Mouse();
    274 		//	Be nice to other apps.
    275 		Sleep( 50 );
    276 
    277 		/*
    278 		**	Get user input.
    279 		*/
    280 		bTabKeyPressedHack = false;
    281 		KeyNumType input = commands->Input();
    282 
    283 		/*
    284 		**	The first time through the processing loop, set the edit
    285 		**	gadget to have the focus. The
    286 		**	focus must be set here since the gadget list has changed
    287 		**	and this change will cause any previous focus setting to be
    288 		**	cleared by the input processing routine.
    289 		*/
    290 		if (firsttime ) {
    291 			firsttime = false;
    292 			NameEdit.Set_Focus();
    293 			NameEdit.Flag_To_Redraw();
    294 		}
    295 
    296 //		/*
    297 //		**	If the <RETURN> key was pressed, then default to the appropriate
    298 //		**	action button according to the style of this dialog box.
    299 //		*/
    300 /*		if (input == KN_RETURN || input == (BUTTON_CONNECT|KN_BUTTON)) {
    301 			ToggleClass * toggle = NULL;
    302 			input = (KeyNumType)(BUTTON_CONNECT|KN_BUTTON);
    303 			CancelBtn.Turn_Off();
    304 			toggle = (ToggleClass*)commands->Extract_Gadget(BUTTON_CONNECT);
    305 			if (toggle != NULL) {
    306 				toggle->Turn_On();
    307 				toggle->IsPressed = true;
    308 			}
    309 
    310 			Hide_Mouse();
    311 			commands->Draw_All(true);
    312 			Show_Mouse();
    313 		}
    314 */
    315 		/*
    316 		**	Process input.
    317 		*/
    318 //		if( input )
    319 //			debugprint( "input: %i\n", input );
    320 
    321 		if( bTabKeyPressedHack )
    322 		{
    323 			if( NameEdit.Has_Focus() )
    324 				PassEdit.Set_Focus();
    325 			else
    326 				NameEdit.Set_Focus();
    327 			NameEdit.Flag_To_Redraw();
    328 			PassEdit.Flag_To_Redraw();
    329 		}
    330 
    331 		switch( input )
    332 		{
    333 			/*
    334 			** ESC/Cancel: break
    335 			*/
    336 			case ( KN_ESC ):
    337 			case ( BUTTON_CANCEL | KN_BUTTON ):
    338 				iReturn = 0;
    339 				process = false;
    340 				break;
    341 
    342 			case KN_RETURN:
    343 			case ( EDITBOX_NAME | KN_BUTTON ):
    344 			case ( EDITBOX_PASS | KN_BUTTON ):
    345 			case ( BUTTON_CONNECT | KN_BUTTON ):
    346 			{
    347 				if( !strlen( szNameBuffer ) )
    348 				{
    349 					WWMessageBox().Process( TXT_WOL_MISSINGNAME );
    350 					firsttime = true;		//	Bloody hack.
    351 					NameEdit.Set_Focus();
    352 					Keyboard->Clear();
    353 					display = true;
    354 					break;
    355 				}
    356 				if( !strlen( szPassBuffer ) )
    357 				{
    358 					WWMessageBox().Process( TXT_WOL_MISSINGPASSWORD );
    359 					firsttime = true;		//	Bloody hack.
    360 					PassEdit.Set_Focus();
    361 					Keyboard->Clear();
    362 					display = true;
    363 					break;
    364 				}
    365 				
    366 				//	If we have not done RequestServerList() yet, do it now.
    367 				if( !pWO->pChatSink->pServer )
    368 				{
    369 					bool bBreak = false;
    370 					HRESULT hRes = pWO->GetChatServer();
    371 					switch( hRes )
    372 					{
    373 					case E_FAIL:
    374 						bBreak = true;
    375 						WWMessageBox().Process( TXT_WOL_CANTCONNECT );
    376 						firsttime = true;		//	Bloody hack.
    377 						NameEdit.Set_Focus();
    378 						Keyboard->Clear();
    379 						display = true;
    380 						break;
    381 					case USERCANCELLED:
    382 						bBreak = true;
    383 						WWMessageBox().Process( TXT_WOL_LOGINCANCEL );
    384 						firsttime = true;		//	Bloody hack.
    385 						NameEdit.Set_Focus();
    386 						Keyboard->Clear();
    387 						display = true;
    388 						break;
    389 					case PATCHAVOIDED:
    390 						bBreak = true;
    391 						firsttime = true;		//	Bloody hack.
    392 						NameEdit.Set_Focus();
    393 						Keyboard->Clear();
    394 						display = true;
    395 						break;
    396 					case PATCHDOWNLOADED:
    397 						bBreak = true;
    398 						process = false;
    399 						iReturn = -1;
    400 						break;
    401 					}
    402 					if( bBreak )
    403 						break;
    404 				}
    405 				
    406 				//	RequestConnection()...
    407 				HRESULT hRes = pWO->AttemptLogin( szNameBuffer, szPassBuffer, PassEdit.bClearOnNextSetFocus );
    408 				if( hRes == S_OK )
    409 				{
    410 					if( SaveCheckBox.IsOn && !bSaveNick( pWO, szNameBuffer, szPassBuffer, PassEdit.bClearOnNextSetFocus ) )
    411 					{
    412 						//	Nick/pass save failed.
    413 						WWMessageBox().Process( TXT_WOL_CANTSAVENICK );
    414 					}
    415 					process = false;
    416 				}
    417 				else
    418 				{
    419 					switch( hRes )
    420 					{
    421 					case USERCANCELLED:
    422 						WWMessageBox().Process( TXT_WOL_LOGINCANCEL );
    423 						break;
    424 					case CHAT_E_TIMEOUT:
    425 						WWMessageBox().Process( TXT_WOL_TIMEOUT );
    426 						break;
    427 					case CHAT_E_BADPASS:
    428 						WWMessageBox().Process( TXT_WOL_BADPASS );
    429 						break;
    430 					case CHAT_E_NICKINUSE:
    431 						WWMessageBox().Process( TXT_WOL_NICKINUSE );
    432 						break;
    433 					case CHAT_E_CON_ERROR:
    434 						//	This error value I pass back myself, when the emergency timeout is hit.
    435 						WWMessageBox().Process( TXT_WOL_TIMEOUT );
    436 						break;
    437 					}
    438 					firsttime = true;		//	Bloody hack.
    439 					NameEdit.Set_Focus();
    440 					Keyboard->Clear();
    441 					display = true;
    442 				}
    443 				break;
    444 			}
    445 
    446 /*
    447 			case( EDITBOX_PASS | KN_BUTTON ):
    448 			{
    449 				//	Message with delay so that user has time to read it...
    450 				CDTimerClass<SystemTimerClass> timer;
    451 				timer = TICKS_PER_SECOND*4;
    452 				WWMessageBox().Process(TXT_WOL_DEBUG2, TXT_NONE);
    453 				while (timer > 0) {
    454 					Call_Back();
    455 				}
    456 				Keyboard->Clear();
    457 
    458 				display = true;
    459 				break;
    460 			}
    461 */
    462 			case ( LISTBOX_NICKS | KN_BUTTON ):
    463 				strcpy( szNameBuffer, NickList.Get_Item( NickList.Current_Index() ) );
    464 				strcpy( szPassBuffer, NickList.Get_Item_ExtraDataString( NickList.Current_Index() ) );
    465 				NameEdit.Flag_To_Redraw();
    466 				PassEdit.Flag_To_Redraw();
    467 				//	Because the password is mangled, if the user begins to edit it now, we clear it.
    468 				//	Otherwise we could get a half-mangled, half-unmangled password field.
    469 				//	PassEdit.bClearOnNextSetFocus also acts as a flag telling us whether or not the
    470 				//	password field is mangled or not.
    471 				PassEdit.bClearOnNextSetFocus = true;
    472 //				display = true;
    473 				break;
    474 
    475 			case ( BUTTON_SAVECHECK | KN_BUTTON ):
    476 				break;
    477 
    478 			case ( BUTTON_DELETE | KN_BUTTON ):
    479 				if( NickList.Count() > 0 )
    480 				{
    481 					DeleteNick( pWO, NickList.Current_Index() + 1 );
    482 					NickList.Remove_Item( NickList.Current_Index() );
    483 					NickList.Flag_To_Redraw();
    484 					if( NickList.Count() == 0 )
    485 					{
    486 						DeleteBtn.Disable();
    487 						DeleteBtn.Flag_To_Redraw();
    488 					}
    489 				}
    490 				break;
    491 
    492 			default:
    493 				break;
    494 		}
    495 	}
    496 
    497 	return iReturn;
    498 }
    499 
    500 //***********************************************************************************************
    501 bool ReadSavedNicks( WolapiObject* pWO, IconListClass& NickList, char* szNameBuffer, char* szPassBuffer )
    502 {
    503 	//	Read saved nickname/passwords from the registry.
    504 	//	Set up the list of nick/passwords.
    505 	//	Copy the first nick into the nick/password edits.
    506 
    507 	//	Returns true if edits are set with a default nick/pass because a nick was found.
    508 
    509 	LPCSTR szNick;
    510 	LPCSTR szPass;
    511 	bool bReturn = false;
    512 
    513 	for( int i = 1; i != 3; i++ )
    514 	{
    515 		if( pWO->pChat->GetNick( i, &szNick, &szPass ) == S_OK )
    516 		{
    517 			if( *szNick )
    518 			{
    519 				NickList.Add_Item( szNick, NULL, NULL, ICON_SHAPE, szPass );
    520 				if( i == 1 )
    521 				{
    522 					strcpy( szNameBuffer, szNick );
    523 					strcpy( szPassBuffer, szPass );
    524 					bReturn = true;
    525 				}
    526 			}
    527 		}
    528 	}
    529 	return bReturn;
    530 }
    531 
    532 //***********************************************************************************************
    533 bool bSaveNick( WolapiObject* pWO, const char* szNickToSave, const char* szPassToSave, bool bPassIsMangled )
    534 {
    535 	//	Saves specified nick and password in the registry, using SetNick.
    536 	//	Returns false if nick can't be saved.
    537 	
    538 	//	If slot 1 empty, use slot 1.
    539 	//	Else push nick 1 down to second slot and save new nick in slot 1, unless
    540 	//	nick 1 name matches new entry.
    541 
    542 	LPCSTR szNick;
    543 	LPCSTR szPass;
    544 	bool bPushSlot1 = true;
    545 
    546 	switch( pWO->pChat->GetNick( 1, &szNick, &szPass ) )
    547 	{
    548 	case E_FAIL:
    549 		//	Assume that this is because there is no registry entry. We can use this slot.
    550 		bPushSlot1 = false;
    551 		break;
    552 	case S_OK:
    553 		if( *szNick == 0 )
    554 			bPushSlot1 = false;			//	We can use this blank slot.
    555 		else
    556 			if( strcmp( szNick, szNickToSave ) == 0 )
    557 				bPushSlot1 = false;		//	We can use this slot as the name is the same.
    558 		break;
    559 	}
    560 
    561 	if( bPushSlot1 )
    562 	{
    563 		//	Move nick in slot 1 to slot 2.
    564 		pWO->pChat->SetNick( 2, szNick, szPass, false );	//	(Already mangled.)
    565 	}
    566 
    567 	//	Save new nick in slot 1.
    568 	return ( pWO->pChat->SetNick( 1, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );
    569 
    570 /*
    571 	int iSlot;
    572 	bool bStop = false;
    573 	for( iSlot = 1; iSlot != 3; iSlot++ )
    574 	{
    575 		switch( pWO->pChat->GetNick( iSlot, &szNick, &szPass ) )
    576 		{
    577 		case E_FAIL:
    578 			//	Assume that this is because there is no registry entry. We can use this slot.
    579 			bStop = true;
    580 			break;
    581 		case S_OK:
    582 			if( *szNick == 0 )
    583 				bStop = true;		//	We can use this blank slot.
    584 			else
    585 				if( strcmp( szNick, szNickToSave ) == 0 )
    586 					bStop = true;	//	We can use this slot as the name is the same.
    587 			break;
    588 		}
    589 		if( bStop )
    590 			break;
    591 	}
    592 	if( iSlot == 3 )
    593 	{
    594 		//	No open slots were found.
    595 		//	Get nick 1.
    596 		pWO->pChat->GetNick( 1, &szNick, &szPass );
    597 		//	Save as nick 2.
    598 		pWO->pChat->SetNick( 2, szNick, szPass, false );	//	(Already mangled.)
    599 		//	Save new nick 1.
    600 		return ( pWO->pChat->SetNick( 1, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );
    601 	}
    602 	else
    603 	{
    604 		//	iSlot points to an open slot.
    605 		return ( pWO->pChat->SetNick( iSlot, szNickToSave, szPassToSave, !bPassIsMangled ) == S_OK );
    606 	}
    607 */
    608 }
    609 
    610 //***********************************************************************************************
    611 void DeleteNick( WolapiObject* pWO, int iOneBasedEntryToDelete )
    612 {
    613 	//	Delete a nick from the registry via wolapi SetNick.
    614 	//	If nick to delete is in position one, and there is a second nick, move the second nick into position one.
    615 	if( iOneBasedEntryToDelete == 1 )
    616 	{
    617 		//	Check for nick 2.
    618 		LPCSTR szNick;
    619 		LPCSTR szPass;
    620 		if( pWO->pChat->GetNick( 2, &szNick, &szPass ) == S_OK && *szNick != 0 )
    621 		{
    622 			//	Copy nick in slot 2 to slot 1.
    623 			pWO->pChat->SetNick( 1, szNick, szPass, false );	//	(Already mangled.)
    624 			//	Delete slot 2.
    625 			HRESULT hRes = pWO->pChat->SetNick( 2, "", "", false );
    626 			DebugChatDef( hRes );
    627 		}
    628 		else
    629 		{
    630 			//	No second nick.
    631 			HRESULT hRes = pWO->pChat->SetNick( 1, "", "", false );
    632 			DebugChatDef( hRes );
    633 		}
    634 	}
    635 	else
    636 	{
    637 		HRESULT hRes = pWO->pChat->SetNick( 2, "", "", false );
    638 		DebugChatDef( hRes );
    639 	}
    640 }
    641 
    642 /*
    643 //***********************************************************************************************
    644 char* LoadShpFile( const char* szShpFile )
    645 {
    646 	//	Returns pointer to shp data that has been new'ed (and must be delete[]d), or NULL if failure.
    647 	//	ajw: No longer needed - I used this before putting new resources into a mix file.
    648 	HANDLE hFile;
    649 	hFile = CreateFile( szShpFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
    650 	if( hFile == INVALID_HANDLE_VALUE )
    651 		return NULL;
    652 	DWORD dwFileSize = GetFileSize( hFile, NULL );
    653 	char* pShp = new char[ dwFileSize ];
    654 	DWORD dwBytesRead;
    655 	ReadFile( hFile, pShp, dwFileSize, &dwBytesRead, NULL );
    656 //	debugprint( "~~ LoadShpFile() - Read %i bytes out of %i from shp file.\n", dwBytesRead, dwFileSize );
    657 	CloseHandle( hFile );
    658 	return pShp;
    659 }
    660 */
    661 
    662 #endif