384 lines
10 KiB
C++
384 lines
10 KiB
C++
|
//
|
||
|
// 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
|
||
|
|
||
|
#ifdef WOLAPI_INTEGRATION
|
||
|
|
||
|
// SEditDlg.cpp - "SimpleEditDlgClass": An ok/cancel type dialog with 1 or 2 edit boxes.
|
||
|
// Mostly a hack for what I need right now - not necessarily very flexible.
|
||
|
// Still - I can't believe there isn't a set of dialog classes in here already.
|
||
|
// ajw 07/21/98
|
||
|
|
||
|
#include "SEditDlg.h"
|
||
|
#include "WOLEdit.h"
|
||
|
|
||
|
extern bool cancel_current_msgbox;
|
||
|
bool disable_current_msgbox = false;
|
||
|
|
||
|
//***********************************************************************************************
|
||
|
SimpleEditDlgClass::SimpleEditDlgClass( int iDialogWidth, const char* szTitle, const char* szPrompt, int iEditCharsAccept,
|
||
|
const char* szPrompt2 /* = NULL */, int iEditCharsAccept2 /* = 0 */ )
|
||
|
: iDialogWidth( iDialogWidth ), iEditCharsAccept( iEditCharsAccept ), iEditCharsAccept2( iEditCharsAccept2 )
|
||
|
{
|
||
|
// Copy strings.
|
||
|
if( szTitle )
|
||
|
{
|
||
|
this->szTitle = new char[ strlen( szTitle ) + 1 ];
|
||
|
strcpy( this->szTitle, szTitle );
|
||
|
}
|
||
|
else
|
||
|
this->szTitle = NULL;
|
||
|
|
||
|
if( szPrompt )
|
||
|
{
|
||
|
this->szPrompt = new char[ strlen( szPrompt ) + 1 ];
|
||
|
strcpy( this->szPrompt, szPrompt );
|
||
|
}
|
||
|
else
|
||
|
this->szPrompt = NULL; // I wouldn't try this ... not totally implemented.
|
||
|
|
||
|
if( szPrompt2 )
|
||
|
{
|
||
|
this->szPrompt2 = new char[ strlen( szPrompt2 ) + 1 ];
|
||
|
strcpy( this->szPrompt2, szPrompt2 );
|
||
|
}
|
||
|
else
|
||
|
this->szPrompt2 = NULL; // This is the flag for whether or not there is a second edit box.
|
||
|
|
||
|
*szEdit = 0;
|
||
|
*szEdit2 = 0;
|
||
|
|
||
|
szOkButton = Text_String( TXT_OK );
|
||
|
szCancelButton = Text_String( TXT_CANCEL );
|
||
|
szMiddleButton = NULL;
|
||
|
}
|
||
|
|
||
|
//***********************************************************************************************
|
||
|
SimpleEditDlgClass::~SimpleEditDlgClass()
|
||
|
{
|
||
|
delete [] szTitle;
|
||
|
delete [] szPrompt;
|
||
|
delete [] szPrompt2;
|
||
|
}
|
||
|
|
||
|
//***********************************************************************************************
|
||
|
void SimpleEditDlgClass::SetButtons( const char* szOk, const char* szCancel, const char* szMiddle /*= NULL*/ )
|
||
|
{
|
||
|
szOkButton = szOk;
|
||
|
szCancelButton = szCancel;
|
||
|
szMiddleButton = szMiddle;
|
||
|
}
|
||
|
|
||
|
//***********************************************************************************************
|
||
|
const char* SimpleEditDlgClass::Show()
|
||
|
{
|
||
|
// Shows dialog, returns text of button pressed.
|
||
|
// Unless SetButtons() is used, value will be TXT_OK or TXT_CANCEL string values.
|
||
|
|
||
|
bool bEscapeDown = false;
|
||
|
bool bReturnDown = false;
|
||
|
|
||
|
/*
|
||
|
** Dialog & button dimensions
|
||
|
*/
|
||
|
int x_margin = 18 * RESFACTOR; // margin width/height
|
||
|
int y_margin = 10 * RESFACTOR; // margin width/height
|
||
|
int d_gap_y = 5 * RESFACTOR;
|
||
|
|
||
|
int d_dialog_w = iDialogWidth;
|
||
|
int d_dialog_h = szPrompt2 ? ( 29 * RESFACTOR ) + 2 * d_gap_y + 2 * y_margin : ( 19 * RESFACTOR ) + d_gap_y + 2 * y_margin;
|
||
|
if( szTitle )
|
||
|
d_dialog_h += 10 * RESFACTOR + 2 * d_gap_y;
|
||
|
int d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2);
|
||
|
int d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2);
|
||
|
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // coord of x-center
|
||
|
|
||
|
/*
|
||
|
if( szTitle )
|
||
|
{
|
||
|
d_title_w = String_Pixel_Width( szTitle );
|
||
|
d_title_h = 10 * RESFACTOR;
|
||
|
d_title_x = d_dialog_cx - d_title_w / 2;
|
||
|
d_title_y = d_dialog_y + d_gap_y;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
int d_prompt_w = String_Pixel_Width( szPrompt );
|
||
|
int d_prompt_h = 10 * RESFACTOR;
|
||
|
int d_prompt_x = d_dialog_x + x_margin;
|
||
|
int d_prompt_y = szTitle ? ( d_dialog_y + 3 * d_gap_y + 10 * RESFACTOR ) : ( d_dialog_y + d_gap_y );
|
||
|
|
||
|
int d_edit_w = d_dialog_w - d_prompt_w - 2 * x_margin;
|
||
|
int d_edit_h = 10 * RESFACTOR;
|
||
|
int d_edit_x = d_dialog_x + d_prompt_w + x_margin;
|
||
|
int d_edit_y = d_prompt_y;
|
||
|
|
||
|
int d_prompt2_w = szPrompt2 ? String_Pixel_Width( szPrompt2 ) : 0;
|
||
|
int d_prompt2_h = 10 * RESFACTOR;
|
||
|
int d_prompt2_x = d_dialog_x + x_margin;
|
||
|
int d_prompt2_y = d_prompt_y + d_prompt2_h + d_gap_y;
|
||
|
|
||
|
int d_edit2_w = d_dialog_w - d_prompt2_w - 2 * x_margin;
|
||
|
int d_edit2_h = 10 * RESFACTOR;
|
||
|
int d_edit2_x = d_dialog_x + d_prompt2_w + x_margin;
|
||
|
int d_edit2_y = d_prompt2_y;
|
||
|
|
||
|
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;
|
||
|
|
||
|
if( !szMiddleButton )
|
||
|
{
|
||
|
d_ok_w = 40 * RESFACTOR;
|
||
|
d_ok_h = 9 * RESFACTOR;
|
||
|
d_ok_x = d_dialog_cx - d_ok_w - 10 * RESFACTOR;
|
||
|
d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;
|
||
|
|
||
|
d_cancel_w = 40 * RESFACTOR;
|
||
|
d_cancel_h = 9 * RESFACTOR;
|
||
|
d_cancel_x = d_dialog_cx + 10 * RESFACTOR;
|
||
|
d_cancel_y = d_ok_y;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
d_ok_w = 40 * RESFACTOR;
|
||
|
d_ok_h = 9 * RESFACTOR;
|
||
|
d_ok_x = d_dialog_cx - d_ok_w - 30 * RESFACTOR;
|
||
|
d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - y_margin;
|
||
|
|
||
|
d_mid_w = 40 * RESFACTOR;
|
||
|
d_mid_h = 9 * RESFACTOR;
|
||
|
d_mid_x = d_dialog_cx - ( d_mid_w / 2 );
|
||
|
d_mid_y = d_ok_y;
|
||
|
|
||
|
d_cancel_w = 40 * RESFACTOR;
|
||
|
d_cancel_h = 9 * RESFACTOR;
|
||
|
d_cancel_x = d_dialog_cx + 30 * RESFACTOR;
|
||
|
d_cancel_y = d_ok_y;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Button enumerations
|
||
|
*/
|
||
|
enum {
|
||
|
BUTTON_OK = 100,
|
||
|
BUTTON_CANCEL,
|
||
|
BUTTON_MIDDLE,
|
||
|
BUTTON_EDIT,
|
||
|
BUTTON_EDIT2
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
** 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
|
||
|
*/
|
||
|
const char* szReturn = NULL;
|
||
|
|
||
|
/*
|
||
|
** Buttons
|
||
|
*/
|
||
|
ControlClass* commands = NULL; // the button list
|
||
|
|
||
|
TextButtonClass OkBtn( BUTTON_OK, szOkButton, TPF_BUTTON, d_ok_x, d_ok_y, d_ok_w );
|
||
|
TextButtonClass CancelBtn( BUTTON_CANCEL, szCancelButton, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );
|
||
|
TextButtonClass MiddleBtn( BUTTON_MIDDLE, szMiddleButton, TPF_BUTTON, d_mid_x, d_mid_y, d_mid_w );
|
||
|
|
||
|
WOLEditClass EditBox( BUTTON_EDIT, szEdit, min( sizeof(szEdit), iEditCharsAccept ), TPF_6PT_GRAD|TPF_NOSHADOW,
|
||
|
d_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC );
|
||
|
WOLEditClass EditBox2( BUTTON_EDIT2, szEdit2, min( sizeof(szEdit2), iEditCharsAccept2 ), TPF_6PT_GRAD|TPF_NOSHADOW,
|
||
|
d_edit2_x, d_edit2_y, d_edit2_w, -1, EditClass::ALPHANUMERIC );
|
||
|
|
||
|
/*
|
||
|
** Initialize.
|
||
|
*/
|
||
|
Set_Logic_Page(SeenBuff);
|
||
|
|
||
|
/*
|
||
|
** Create the button list.
|
||
|
*/
|
||
|
commands = &OkBtn;
|
||
|
CancelBtn.Add_Tail(*commands);
|
||
|
if( szMiddleButton )
|
||
|
MiddleBtn.Add_Tail(*commands);
|
||
|
EditBox.Add_Tail(*commands);
|
||
|
if( szPrompt2 )
|
||
|
EditBox2.Add_Tail(*commands);
|
||
|
EditBox.Set_Focus();
|
||
|
|
||
|
/*
|
||
|
** Main Processing Loop.
|
||
|
*/
|
||
|
Keyboard->Clear();
|
||
|
bool firsttime = true;
|
||
|
bool display = true;
|
||
|
bool process = 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 = true;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
** Refresh display if needed.
|
||
|
*/
|
||
|
if (display) {
|
||
|
|
||
|
/*
|
||
|
** Display the dialog box.
|
||
|
*/
|
||
|
Hide_Mouse();
|
||
|
if (display) {
|
||
|
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
|
||
|
if( szTitle )
|
||
|
Draw_Caption( szTitle, d_dialog_x, d_dialog_y, d_dialog_w );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Redraw the buttons.
|
||
|
*/
|
||
|
if (display) {
|
||
|
Fancy_Text_Print( szPrompt, d_prompt_x, d_prompt_y,
|
||
|
GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );
|
||
|
if( szPrompt2 )
|
||
|
Fancy_Text_Print( szPrompt2, d_prompt2_x, d_prompt2_y,
|
||
|
GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT );
|
||
|
|
||
|
commands->Flag_List_To_Redraw();
|
||
|
}
|
||
|
Show_Mouse();
|
||
|
display = false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Get user input.
|
||
|
*/
|
||
|
KeyNumType input = commands->Input();
|
||
|
|
||
|
/*
|
||
|
** The first time through the processing loop, set the edit
|
||
|
** gadget to have the focus. The
|
||
|
** focus must be set here since the gadget list has changed
|
||
|
** and this change will cause any previous focus setting to be
|
||
|
** cleared by the input processing routine.
|
||
|
*/
|
||
|
if (firsttime ) {
|
||
|
firsttime = false;
|
||
|
EditBox.Set_Focus();
|
||
|
EditBox.Flag_To_Redraw();
|
||
|
}
|
||
|
|
||
|
// My hack for triggering escape and return on key up instead of down...
|
||
|
// The problem that was occurring was that the calling dialog would act on the key up,
|
||
|
// though this dialog handled the key down. ajw
|
||
|
if( ( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) )
|
||
|
{
|
||
|
bEscapeDown = true;
|
||
|
}
|
||
|
else if( bEscapeDown )
|
||
|
{
|
||
|
input = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );
|
||
|
bEscapeDown = false;
|
||
|
}
|
||
|
if( ( ::GetAsyncKeyState( VK_RETURN ) & 0x8000 ) )
|
||
|
{
|
||
|
bReturnDown = true;
|
||
|
}
|
||
|
else if( bReturnDown )
|
||
|
{
|
||
|
input = (KeyNumType)( BUTTON_OK | KN_BUTTON );
|
||
|
bReturnDown = false;
|
||
|
}
|
||
|
|
||
|
// I really hate to do this, but... ajw
|
||
|
if( cancel_current_msgbox )
|
||
|
{
|
||
|
cancel_current_msgbox = false;
|
||
|
input = (KeyNumType)( BUTTON_CANCEL | KN_BUTTON );
|
||
|
}
|
||
|
|
||
|
if( disable_current_msgbox )
|
||
|
{
|
||
|
disable_current_msgbox = false;
|
||
|
EditBox.Disable();
|
||
|
// These do not actually draw. I am actually clearing the "draw" flag!
|
||
|
// Problem is Disable sets them to redraw, and I don't want to, and there is no Flag_To_Redraw( false ).
|
||
|
EditBox.GadgetClass::Draw_Me( true );
|
||
|
if( szPrompt2 )
|
||
|
{
|
||
|
EditBox2.Disable();
|
||
|
EditBox2.GadgetClass::Draw_Me( true );
|
||
|
}
|
||
|
OkBtn.Disable();
|
||
|
OkBtn.GadgetClass::Draw_Me( true );
|
||
|
CancelBtn.Disable();
|
||
|
CancelBtn.GadgetClass::Draw_Me( true );
|
||
|
if( szMiddleButton )
|
||
|
{
|
||
|
MiddleBtn.Disable();
|
||
|
MiddleBtn.GadgetClass::Draw_Me( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** Process input.
|
||
|
*/
|
||
|
switch( input )
|
||
|
{
|
||
|
// case ( KN_ESC ):
|
||
|
case ( BUTTON_CANCEL | KN_BUTTON ):
|
||
|
szReturn = szCancelButton;
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
// case KN_RETURN:
|
||
|
case ( BUTTON_EDIT | KN_BUTTON ): // (Return pressed while on edit.)
|
||
|
case ( BUTTON_OK | KN_BUTTON ):
|
||
|
szReturn = szOkButton;
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
case ( BUTTON_MIDDLE | KN_BUTTON ):
|
||
|
szReturn = szMiddleButton;
|
||
|
process = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return szReturn;
|
||
|
}
|
||
|
|
||
|
#endif
|