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