SEDITDLG.CPP (10586B)
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 // SEditDlg.cpp - "SimpleEditDlgClass": An ok/cancel type dialog with 1 or 2 edit boxes. 19 // Mostly a hack for what I need right now - not necessarily very flexible. 20 // Still - I can't believe there isn't a set of dialog classes in here already. 21 // ajw 07/21/98 22 23 #include "SEditDlg.h" 24 #include "WOLEdit.h" 25 26 extern bool cancel_current_msgbox; 27 bool disable_current_msgbox = false; 28 29 //*********************************************************************************************** 30 SimpleEditDlgClass::SimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept, 31 const char* szPrompt2 /* = NULL */, int iEditCharsAccept2 /* = 0 */ ) 32 : iDialogWidth( iDialogWidth ), iEditCharsAccept( iEditCharsAccept ), iEditCharsAccept2( iEditCharsAccept2 ) 33 { 34 // Copy strings. 35 if( szTitle ) 36 { 37 this->szTitle = new char[ strlen( szTitle ) + 1 ]; 38 strcpy( this->szTitle, szTitle ); 39 } 40 else 41 this->szTitle = NULL; 42 43 if( szPrompt ) 44 { 45 this->szPrompt = new char[ strlen( szPrompt ) + 1 ]; 46 strcpy( this->szPrompt, szPrompt ); 47 } 48 else 49 this->szPrompt = NULL; // I wouldn't try this ... not totally implemented. 50 51 if( szPrompt2 ) 52 { 53 this->szPrompt2 = new char[ strlen( szPrompt2 ) + 1 ]; 54 strcpy( this->szPrompt2, szPrompt2 ); 55 } 56 else 57 this->szPrompt2 = NULL; // This is the flag for whether or not there is a second edit box. 58 59 *szEdit = 0; 60 *szEdit2 = 0; 61 62 szOkButton = Text_String( TXT_OK ); 63 szCancelButton = Text_String( TXT_CANCEL ); 64 szMiddleButton = NULL; 65 } 66 67 //*********************************************************************************************** 68 SimpleEditDlgClass::~SimpleEditDlgClass() 69 { 70 delete [] szTitle; 71 delete [] szPrompt; 72 delete [] szPrompt2; 73 } 74 75 //*********************************************************************************************** 76 void SimpleEditDlgClass::SetButtons( const char* szOk, const char* szCancel, const char* szMiddle /*= NULL*/ ) 77 { 78 szOkButton = szOk; 79 szCancelButton = szCancel; 80 szMiddleButton = szMiddle; 81 } 82 83 //*********************************************************************************************** 84 const char* SimpleEditDlgClass::Show() 85 { 86 // Shows dialog, returns text of button pressed. 87 // Unless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values. 88 89 bool bEscapeDown = false; 90 bool bReturnDown = false; 91 92 /* 93 ** Dialog & button dimensions 94 */ 95 int x_margin = 18 * RESFACTOR; // margin width/height 96 int y_margin = 10 * RESFACTOR; // margin width/height 97 int d_gap_y = 5 * RESFACTOR; 98 99 int d_dialog_w = iDialogWidth; 100 int d_dialog_h = szPrompt2 ? ( 29 * RESFACTOR ) + 2 * d_gap_y + 2 * y_margin : ( 19 * RESFACTOR ) + d_gap_y + 2 * y_margin; 101 if( szTitle ) 102 d_dialog_h += 10 * RESFACTOR + 2 * d_gap_y; 103 int d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2); 104 int d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2); 105 int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // coord of x-center 106 107 /* 108 if( szTitle ) 109 { 110 d_title_w = String_Pixel_Width( szTitle ); 111 d_title_h = 10 * RESFACTOR; 112 d_title_x = d_dialog_cx - d_title_w / 2; 113 d_title_y = d_dialog_y + d_gap_y; 114 } 115 */ 116 117 int d_prompt_w = String_Pixel_Width( szPrompt ); 118 int d_prompt_h = 10 * RESFACTOR; 119 int d_prompt_x = d_dialog_x + x_margin; 120 int d_prompt_y = szTitle ? ( d_dialog_y + 3 * d_gap_y + 10 * RESFACTOR ) : ( d_dialog_y + d_gap_y ); 121 122 int d_edit_w = d_dialog_w - d_prompt_w - 2 * x_margin; 123 int d_edit_h = 10 * RESFACTOR; 124 int d_edit_x = d_dialog_x + d_prompt_w + x_margin; 125 int d_edit_y = d_prompt_y; 126 127 int d_prompt2_w = szPrompt2 ? String_Pixel_Width( szPrompt2 ) : 0; 128 int d_prompt2_h = 10 * RESFACTOR; 129 int d_prompt2_x = d_dialog_x + x_margin; 130 int d_prompt2_y = d_prompt_y + d_prompt2_h + d_gap_y; 131 132 int d_edit2_w = d_dialog_w - d_prompt2_w - 2 * x_margin; 133 int d_edit2_h = 10 * RESFACTOR; 134 int d_edit2_x = d_dialog_x + d_prompt2_w + x_margin; 135 int d_edit2_y = d_prompt2_y; 136 137 int d_ok_w, d_ok_h, d_ok_x, d_ok_y, d_cancel_w, d_cancel_h, d_cancel_x, d_cancel_y, d_mid_x, d_mid_y, d_mid_w, d_mid_h; 138 139 if( !szMiddleButton ) 140 { 141 d_ok_w = 40 * RESFACTOR; 142 d_ok_h = 9 * RESFACTOR; 143 d_ok_x = d_dialog_cx - d_ok_w - 10 * RESFACTOR; 144 d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin; 145 146 d_cancel_w = 40 * RESFACTOR; 147 d_cancel_h = 9 * RESFACTOR; 148 d_cancel_x = d_dialog_cx + 10 * RESFACTOR; 149 d_cancel_y = d_ok_y; 150 } 151 else 152 { 153 d_ok_w = 40 * RESFACTOR; 154 d_ok_h = 9 * RESFACTOR; 155 d_ok_x = d_dialog_cx - d_ok_w - 30 * RESFACTOR; 156 d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin; 157 158 d_mid_w = 40 * RESFACTOR; 159 d_mid_h = 9 * RESFACTOR; 160 d_mid_x = d_dialog_cx - ( d_mid_w / 2 ); 161 d_mid_y = d_ok_y; 162 163 d_cancel_w = 40 * RESFACTOR; 164 d_cancel_h = 9 * RESFACTOR; 165 d_cancel_x = d_dialog_cx + 30 * RESFACTOR; 166 d_cancel_y = d_ok_y; 167 } 168 169 /* 170 ** Button enumerations 171 */ 172 enum { 173 BUTTON_OK = 100, 174 BUTTON_CANCEL, 175 BUTTON_MIDDLE, 176 BUTTON_EDIT, 177 BUTTON_EDIT2 178 }; 179 180 /* 181 ** Redraw values: in order from "top" to "bottom" layer of the dialog 182 */ 183 typedef enum { 184 REDRAW_NONE = 0, 185 REDRAW_BUTTONS, 186 REDRAW_BACKGROUND, 187 REDRAW_ALL = REDRAW_BACKGROUND 188 } RedrawType; 189 190 /* 191 ** Dialog variables 192 */ 193 const char* szReturn = NULL; 194 195 /* 196 ** Buttons 197 */ 198 ControlClass* commands = NULL; // the button list 199 200 TextButtonClass OkBtn( BUTTON_OK, szOkButton, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w ); 201 TextButtonClass CancelBtn( BUTTON_CANCEL, szCancelButton, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w ); 202 TextButtonClass MiddleBtn( BUTTON_MIDDLE, szMiddleButton, TPF_BUTTON, d_mid_x, d_mid_y, d_mid_w ); 203 204 WOLEditClass EditBox( BUTTON_EDIT, szEdit, min( sizeof(szEdit), iEditCharsAccept ), TPF_6PT_GRAD|TPF_NOSHADOW, 205 d_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC ); 206 WOLEditClass EditBox2( BUTTON_EDIT2, szEdit2, min( sizeof(szEdit2), iEditCharsAccept2 ), TPF_6PT_GRAD|TPF_NOSHADOW, 207 d_edit2_x, d_edit2_y, d_edit2_w, -1, EditClass::ALPHANUMERIC ); 208 209 /* 210 ** Initialize. 211 */ 212 Set_Logic_Page(SeenBuff); 213 214 /* 215 ** Create the button list. 216 */ 217 commands = &OkBtn; 218 CancelBtn.Add_Tail(*commands); 219 if( szMiddleButton ) 220 MiddleBtn.Add_Tail(*commands); 221 EditBox.Add_Tail(*commands); 222 if( szPrompt2 ) 223 EditBox2.Add_Tail(*commands); 224 EditBox.Set_Focus(); 225 226 /* 227 ** Main Processing Loop. 228 */ 229 Keyboard->Clear(); 230 bool firsttime = true; 231 bool display = true; 232 bool process = true; 233 while (process) { 234 235 /* 236 ** Invoke game callback. 237 */ 238 Call_Back(); 239 240 #ifdef WIN32 241 /* 242 ** If we have just received input focus again after running in the background then 243 ** we need to redraw. 244 */ 245 if (AllSurfaces.SurfacesRestored) { 246 AllSurfaces.SurfacesRestored=FALSE; 247 display = true; 248 } 249 #endif 250 251 /* 252 ** Refresh display if needed. 253 */ 254 if (display) { 255 256 /* 257 ** Display the dialog box. 258 */ 259 Hide_Mouse(); 260 if (display) { 261 Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); 262 if( szTitle ) 263 Draw_Caption( szTitle, d_dialog_x, d_dialog_y, d_dialog_w ); 264 } 265 266 /* 267 ** Redraw the buttons. 268 */ 269 if (display) { 270 Fancy_Text_Print( szPrompt, d_prompt_x, d_prompt_y, 271 GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT ); 272 if( szPrompt2 ) 273 Fancy_Text_Print( szPrompt2, d_prompt2_x, d_prompt2_y, 274 GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT ); 275 276 commands->Flag_List_To_Redraw(); 277 } 278 Show_Mouse(); 279 display = false; 280 } 281 282 /* 283 ** Get user input. 284 */ 285 KeyNumType input = commands->Input(); 286 287 /* 288 ** The first time through the processing loop, set the edit 289 ** gadget to have the focus. The 290 ** focus must be set here since the gadget list has changed 291 ** and this change will cause any previous focus setting to be 292 ** cleared by the input processing routine. 293 */ 294 if (firsttime ) { 295 firsttime = false; 296 EditBox.Set_Focus(); 297 EditBox.Flag_To_Redraw(); 298 } 299 300 // My hack for triggering escape and return on key up instead of down... 301 // The problem that was occurring was that the calling dialog would act on the key up, 302 // though this dialog handled the key down. ajw 303 if( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) ) 304 { 305 bEscapeDown = true; 306 } 307 else if( bEscapeDown ) 308 { 309 input = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON ); 310 bEscapeDown = false; 311 } 312 if( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) ) 313 { 314 bReturnDown = true; 315 } 316 else if( bReturnDown ) 317 { 318 input = (KeyNumType)( BUTTON_OK | KN_BUTTON ); 319 bReturnDown = false; 320 } 321 322 // I really hate to do this, but... ajw 323 if( cancel_current_msgbox ) 324 { 325 cancel_current_msgbox = false; 326 input = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON ); 327 } 328 329 if( disable_current_msgbox ) 330 { 331 disable_current_msgbox = false; 332 EditBox.Disable(); 333 // These do not actually draw. I am actually clearing the "draw" flag! 334 // Problem is Disable sets them to redraw, and I don't want to, and there is no Flag_To_Redraw( false ). 335 EditBox.GadgetClass::Draw_Me( true ); 336 if( szPrompt2 ) 337 { 338 EditBox2.Disable(); 339 EditBox2.GadgetClass::Draw_Me( true ); 340 } 341 OkBtn.Disable(); 342 OkBtn.GadgetClass::Draw_Me( true ); 343 CancelBtn.Disable(); 344 CancelBtn.GadgetClass::Draw_Me( true ); 345 if( szMiddleButton ) 346 { 347 MiddleBtn.Disable(); 348 MiddleBtn.GadgetClass::Draw_Me( true ); 349 } 350 } 351 352 /* 353 ** Process input. 354 */ 355 switch( input ) 356 { 357 // case ( KN_ESC ): 358 case ( BUTTON_CANCEL | KN_BUTTON ): 359 szReturn = szCancelButton; 360 process = false; 361 break; 362 363 // case KN_RETURN: 364 case ( BUTTON_EDIT | KN_BUTTON ): // (Return pressed while on edit.) 365 case ( BUTTON_OK | KN_BUTTON ): 366 szReturn = szOkButton; 367 process = false; 368 break; 369 370 case ( BUTTON_MIDDLE | KN_BUTTON ): 371 szReturn = szMiddleButton; 372 process = false; 373 break; 374 375 default: 376 break; 377 } 378 } 379 380 return szReturn; 381 } 382 383 #endif