CnC_Remastered_Collection

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

MSGBOX.CPP (18261B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/MSGBOX.CPP 1     3/03/97 10:25a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : OPTIONS.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : June 8, 1994                                                 *
     28  *                                                                                             *
     29  *                  Last Update : August 24, 1995 [JLB]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   WWMessageBox::Process -- Handles all the options graphic interface.                       *
     34  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     35 
     36 #include	"function.h"
     37 #include	"msgbox.h"
     38 #include "gadget.h"
     39 
     40 
     41 #ifdef FIXIT_VERSION_3
     42 bool cancel_current_msgbox = false;
     43 #endif
     44 
     45 /***********************************************************************************************
     46  * WWMessageBox::Process -- pops up a message with yes/no, etc                                 *
     47  *                                                                                             *
     48  * This function displays a dialog box with a one-line message, and                            *
     49  * up to two buttons. The 2nd button is optional. The buttons default                          *
     50  * to "OK" and nothing, respectively. The hotkeys for the buttons are                          *
     51  * RETURN and ESCAPE.                                                                          *
     52  *                                                                                             *
     53  * INPUT:                                                                                      *
     54  *      msg         message to display                                                         *
     55  *      b1txt         text for 1st button                                                      *
     56  *      b2txt         text for 2nd button; NULL = no 2nd button                                *
     57  *                                                                                             *
     58  * OUTPUT:                                                                                     *
     59  *      # of button selected (0 = 1st)                                                         *
     60  *                                                                                             *
     61  * WARNINGS:                                                                                   *
     62  *      'msg' text must be <= 38 chars                                                         *
     63  *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *
     64  *                                                                                             *
     65  * HISTORY:                                                                                    *
     66  *   11/08/1994 BR : Created.                                                                  *
     67  *   05/18/1995 JLB : Uses new font and dialog style.                                          *
     68  *   08/24/1995 JLB : Handles three buttons.                                                   *
     69  *=============================================================================================*/
     70 #define	BUTTON_1		1
     71 #define	BUTTON_2		2
     72 #define	BUTTON_3		3
     73 #define	BUTTON_FLAG	0x8000
     74 int WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2txt, const char * b3txt, bool preserve)
     75 {
     76 #define BUFFSIZE (511)
     77 	char buffer[BUFFSIZE];
     78 	int retval;
     79 	bool process;								// loop while true
     80 	int selection;
     81 	bool pressed;
     82 	int curbutton;
     83 	TextButtonClass * buttons[3];
     84 	void * back;
     85 	BOOL display;									// display level
     86 	int  realval[5];
     87 
     88 #ifndef WIN32
     89 	int	preservex,preservey,preservew,preserveh;
     90 #endif
     91 
     92 	#ifdef WIN32
     93 	GraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);
     94 	#endif
     95 
     96 	if (b1txt != NULL && *b1txt == '\0') b1txt = NULL;
     97 	if (b2txt != NULL && *b2txt == '\0') b2txt = NULL;
     98 	if (b3txt != NULL && *b3txt == '\0') b3txt = NULL;
     99 
    100 	//PG_TO_FIX
    101 	//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);
    102 
    103 	/*
    104 	**	Examine the optional button parameters. Fetch the width and starting
    105 	**	characters for each.
    106 	*/
    107 	int bwidth, bheight;				// button width and height
    108 	int numbuttons = 0;
    109 	if (b1txt != NULL) {
    110 
    111 		/*
    112 		**	Build the button list.
    113 		*/
    114 		bheight = FontHeight + FontYSpacing + (2 * RESFACTOR);
    115 		bwidth = max((String_Pixel_Width(b1txt) + (8 * RESFACTOR)), (30 * RESFACTOR));
    116 
    117 		if (b2txt != NULL) {
    118 			numbuttons = 2;
    119 			bwidth = max(((int)String_Pixel_Width( b2txt ) + (8 * RESFACTOR)), bwidth);
    120 
    121 			if (b3txt != NULL) {
    122 				numbuttons = 3;
    123 			}
    124 
    125 		} else {
    126 			numbuttons = 1;
    127 		}
    128 	}
    129 
    130 	/*
    131 	**	Determine the dimensions of the text to be used for the dialog box.
    132 	**	These dimensions will control how the dialog box looks.
    133 	*/
    134 	buffer[BUFFSIZE-1] = 0;
    135 	strncpy(buffer, msg, BUFFSIZE-1);
    136 	//PG_TO_FIX
    137 	//Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);
    138 	int width;
    139 	int height;
    140 	int lines = Format_Window_String(buffer, 255 * RESFACTOR, width, height);
    141 	TextPrintType tpf = TPF_TEXT;
    142 
    143 	width = max(width, (90 * RESFACTOR));
    144 	width += 40 * RESFACTOR;
    145 	height += (numbuttons == 0) ? (40 * RESFACTOR) : (60 * RESFACTOR);
    146 
    147 	int x = (SeenBuff.Get_Width() - width) / 2;
    148 	int y = (SeenBuff.Get_Height() - height) / 2;
    149 	int printx = x + (20 * RESFACTOR);
    150 
    151 	/*
    152 	**	Special hack to center a one line dialog box text.
    153 	*/
    154 	if (lines == 1) {
    155 		printx = x + width/2;
    156 		tpf = tpf | TPF_CENTER;
    157 	}
    158 
    159 	/*
    160 	**	Other inits.
    161 	*/
    162 	Set_Logic_Page(SeenBuff);
    163 	#ifdef WIN32
    164 	VisiblePage.Blit(seen_buff_save);
    165 	#endif
    166 
    167 	/*
    168 	**	Initialize the button structures. All are initialized, even though one (or none) may
    169 	**	actually be added to the button list.
    170 	*/
    171 	//DOS BUILD GERMAN BUTTONS NEED TO ONE ON TOP OF THE OTHER  VG 11/6/96
    172 	TextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,
    173 		x + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
    174 
    175 	/*
    176 	**	Center button.
    177 	*/
    178 	TextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,
    179 		x + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
    180 
    181 	/*
    182 	**	Right button.
    183 	*/
    184 	TextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON, 0, y + height - (bheight + (15 * RESFACTOR)));
    185 	button3.X = x + ((width - button3.Width) >> 1);
    186 
    187 	TextButtonClass * buttonlist = 0;
    188 	curbutton = 0;
    189 
    190 	/*
    191 	**	Add and initialize the buttons to the button list.
    192 	*/
    193 	memset(buttons, '\0', sizeof(buttons));
    194 	if (numbuttons > 0) {
    195 		buttonlist = &button1;
    196 		buttons[0] = &button1;
    197 		realval[0] = BUTTON_1;
    198 		if (numbuttons > 2) {
    199 			button3.Add(*buttonlist);
    200 			buttons[1] = &button3;
    201 			realval[1] = BUTTON_3;
    202 			button2.Add(*buttonlist);
    203 			buttons[2] = &button2;
    204 			realval[2] = BUTTON_2;
    205 			buttons[curbutton]->Turn_On();
    206 		} else {
    207 			if (numbuttons == 2) {
    208 				button2.Add(*buttonlist);
    209 				buttons[1] = &button2;
    210 				realval[1] = BUTTON_2;
    211 				buttons[curbutton]->Turn_On();
    212 			}
    213 		}
    214 	}
    215 
    216 	/*
    217 	**	Draw the dialog.
    218 	*/
    219 	Hide_Mouse();
    220 	if (preserve) {
    221 #ifndef WIN32
    222 	preservex = max(0, x-4);
    223 	preservey = max(0, y-4);
    224 	preservew = min(width+8, 320-preservex);
    225 	preserveh = min(height+8, 200-preservey);
    226 	back = new char[preservew * preserveh];
    227 	SeenBuff.To_Buffer(preservex, preservey, preservew, preserveh, back, preservew * preserveh);
    228 #else
    229 		back = new char[width * height];
    230 		SeenBuff.To_Buffer(x, y, width, height, back, width * height);
    231 #endif
    232 	}
    233 	Dialog_Box(x, y, width, height);
    234 	Draw_Caption(Caption, x, y, width);
    235 
    236 	/*
    237 	**	Draw the body of the message.
    238 	*/
    239 	Fancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);
    240 
    241 	/*
    242 	**	Redraw the buttons.
    243 	*/
    244 	if (buttonlist) {
    245 		buttonlist->Draw_All();
    246 	}
    247 	Show_Mouse();
    248 
    249 	/*
    250 	**	Main Processing Loop.
    251 	*/
    252 	if (buttonlist) {
    253 		process = true;
    254 		pressed = false;
    255 		while (process) {
    256 
    257 			#ifdef WIN32
    258 			/*
    259 			** If we have just received input focus again after running in the background then
    260 			** we need to redraw.
    261 			*/
    262 			if (AllSurfaces.SurfacesRestored) {
    263 				AllSurfaces.SurfacesRestored = false;
    264 				seen_buff_save.Blit(VisiblePage);
    265 				display = true;
    266 			}
    267 			#endif
    268 
    269 			if (display) {
    270 				display = false;
    271 
    272 				Hide_Mouse();
    273 				Dialog_Box(x, y, width, height);
    274 				Draw_Caption(Caption, x, y, width);
    275 
    276 				/*
    277 				**	Draw the body of the message.
    278 				*/
    279 				Fancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);
    280 
    281 				/*
    282 				**	Redraw the buttons.
    283 				*/
    284 				if (buttonlist) {
    285 					buttonlist->Draw_All();
    286 				}
    287 				Show_Mouse();
    288 			}
    289 
    290 			/*
    291 			**	Invoke game callback.
    292 			*/
    293 			Call_Back();
    294 
    295 			/*
    296 			**	Fetch and process input.
    297 			*/
    298 			KeyNumType input = buttonlist->Input();
    299 #ifdef FIXIT_VERSION_3
    300 			//	I really hate to do this, but...      ajw
    301 			if( cancel_current_msgbox )
    302 			{
    303 				cancel_current_msgbox = false;
    304 				input = KN_ESC;
    305 			}
    306 #endif
    307 			switch (input) {
    308 				case (KN_ESC):
    309 					selection = realval[numbuttons-1];
    310 					pressed = true;
    311 
    312 #ifdef NEVER
    313 					if (numbuttons > 2) {
    314 						selection = realval[1];
    315 						pressed = true;
    316 					} else {
    317 						selection = realval[2];
    318 						pressed = true;
    319 					}
    320 #endif
    321 					break;
    322 
    323 				case (BUTTON_1|BUTTON_FLAG):
    324 					selection = realval[0];
    325 					pressed = true;
    326 					break;
    327 
    328 				case (BUTTON_2|BUTTON_FLAG):
    329 					if (numbuttons > 2) {
    330 						selection = realval[2];
    331 					} else {
    332 						selection = realval[1];
    333 					}
    334 					pressed = true;
    335 					break;
    336 
    337 				case (BUTTON_3|BUTTON_FLAG):
    338 					selection = realval[1];
    339 					pressed = true;
    340 					break;
    341 
    342 				case (KN_LEFT):
    343 					if (numbuttons > 1) {
    344 						buttons[curbutton]->Turn_Off();
    345 						buttons[curbutton]->Flag_To_Redraw();
    346 
    347 						curbutton--;
    348 						if (curbutton < 0) {
    349 							curbutton = numbuttons - 1;
    350 						}
    351 
    352 						buttons[curbutton]->Turn_On();
    353 						buttons[curbutton]->Flag_To_Redraw();
    354 					}
    355 					break;
    356 
    357 				case (KN_RIGHT):
    358 					if (numbuttons > 1) {
    359 						buttons[curbutton]->Turn_Off();
    360 						buttons[curbutton]->Flag_To_Redraw();
    361 
    362 						curbutton++;
    363 						if (curbutton > (numbuttons - 1) ) {
    364 							curbutton = 0;
    365 						}
    366 
    367 						buttons[curbutton]->Turn_On();
    368 						buttons[curbutton]->Flag_To_Redraw();
    369 					}
    370 					break;
    371 
    372 				case (KN_RETURN):
    373 					selection = realval[curbutton];
    374 					pressed = true;
    375 					break;
    376 
    377 				/*
    378 				**	Check 'input' to see if it's the 1st char of button text
    379 				*/
    380 				default:
    381 					break;
    382 			}
    383 
    384 			if (pressed) {
    385 
    386 				TextButtonClass * toggle;
    387 				/*
    388 				**	Turn all the buttons off.
    389 				*/
    390 				toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_1);
    391 				if (toggle != NULL) {
    392 					toggle->Turn_Off();
    393 					toggle->IsPressed = false;
    394 				}
    395 				toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_2);
    396 				if (toggle != NULL) {
    397 					toggle->Turn_Off();
    398 					toggle->IsPressed = false;
    399 				}
    400 				toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_3);
    401 				if (toggle != NULL) {
    402 					toggle->Turn_Off();
    403 					toggle->IsPressed = false;
    404 				}
    405 
    406 				/*
    407 				**	Turn on and depress the button that was selected.
    408 				*/
    409 				if (selection == BUTTON_1 || selection == BUTTON_2 || selection == BUTTON_3) {
    410 					TextButtonClass * toggle = (TextButtonClass *)buttonlist->Extract_Gadget(selection);
    411 					if (toggle != NULL) {
    412 						toggle->Turn_On();
    413 //						toggle->IsOn = true;
    414 						toggle->IsPressed = true;
    415 					}
    416 				}
    417 				Hide_Mouse();
    418 				buttonlist->Draw_All(true);
    419 				Show_Mouse();
    420 
    421 				switch (selection) {
    422 					case (BUTTON_1):
    423 						retval = 0;
    424 						process = false;
    425 						break;
    426 
    427 					case (BUTTON_2):
    428 						retval = 1;
    429 						process = false;
    430 						break;
    431 
    432 					case BUTTON_3:
    433 						retval = 2;
    434 						process = false;
    435 						break;
    436 				}
    437 
    438 				pressed = false;
    439 			}
    440 		}
    441 
    442 	} else {
    443 
    444 		Keyboard->Clear();
    445 	}
    446 
    447 	/*
    448 	**	Restore the screen if necessary.
    449 	*/
    450 	if (preserve) {
    451 		Hide_Mouse();
    452 		if (SeenBuff.Lock()) {
    453 			#ifdef WIN32
    454 				Buffer_To_Page(x, y, width, height, back, &SeenBuff);
    455 			#else
    456 				MCGA_Buffer_To_Page(preservex, preservey, preservew, preserveh, back, &SeenBuff);
    457 			#endif
    458 		}
    459 		SeenBuff.Unlock();
    460 
    461 		delete[] back;
    462 		back = NULL;
    463 		Show_Mouse();
    464 	}
    465 	return(retval);
    466 }
    467 
    468 
    469 /***********************************************************************************************
    470  * WWMessageBox::Process -- this one takes integer text arguments                              *
    471  *                                                                                             *
    472  * INPUT:                                                                                      *
    473  *      msg         message to display                                                         *
    474  *      b1txt         text for 1st button                                                      *
    475  *      b2txt         text for 2nd button; NULL = no 2nd button                                *
    476  *                                                                                             *
    477  * OUTPUT:                                                                                     *
    478  *      # of button selected (0 = 1st)                                                         *
    479  *                                                                                             *
    480  * WARNINGS:                                                                                   *
    481  *      'msg' text must be <= 38 chars                                                         *
    482  *      'b1txt' and 'b2txt' must each be <= 18 chars                                           *
    483  *                                                                                             *
    484  * HISTORY:                                                                                    *
    485  *   12/12/1994 BR : Created.                                                                  *
    486  *   06/18/1995 JLB : Simplified.                                                              *
    487  *=============================================================================================*/
    488 int WWMessageBox::Process(int msg, int b1txt, int b2txt, int b3txt, bool preserve)
    489 {
    490 	return(Process(Text_String(msg), b1txt, b2txt, b3txt, preserve));
    491 }
    492 
    493 
    494 /***********************************************************************************************
    495  * WWMessageBox::Process -- Displays message box.                                              *
    496  *                                                                                             *
    497  *    This routine will display a message box and wait for player input. It varies from the    *
    498  *    other message box functions only in the type of parameters it takes.                     *
    499  *                                                                                             *
    500  * INPUT:   msg   -- Pointer to text string for the message itself.                            *
    501  *                                                                                             *
    502  *          b1txt -- Text number for the "ok" button.                                          *
    503  *                                                                                             *
    504  *          b2txt -- Text number for the "cancel" button.                                      *
    505  *                                                                                             *
    506  * OUTPUT:  Returns with the button selected. "true" if "OK" was pressed, and "false" if       *
    507  *          "CANCEL" was pressed.                                                              *
    508  *                                                                                             *
    509  * WARNINGS:   none                                                                            *
    510  *                                                                                             *
    511  * HISTORY:                                                                                    *
    512  *   06/18/1995 JLB : Created.                                                                 *
    513  *=============================================================================================*/
    514 int WWMessageBox::Process(char const * msg, int b1txt, int b2txt, int b3txt, bool preserve)
    515 {
    516 	return(Process(msg, Text_String(b1txt), Text_String(b2txt), Text_String(b3txt), preserve));
    517 }