SEDITDLG.CPP 10 KB

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