SEDITDLG.CPP 10 KB

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