MSGBOX.CPP.BAK 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  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. /* $Header: F:\projects\c&c0\vcs\code\msgbox.cpv 4.83 29 Oct 1996 23:49:56 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : OPTIONS.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : June 8, 1994 *
  30. * *
  31. * Last Update : August 24, 1995 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * WWMessageBox::Process -- Handles all the options graphic interface. *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "function.h"
  38. #include "msgbox.h"
  39. #include "gadget.h"
  40. /***********************************************************************************************
  41. * WWMessageBox::Process -- pops up a message with yes/no, etc *
  42. * *
  43. * This function displays a dialog box with a one-line message, and *
  44. * up to two buttons. The 2nd button is optional. The buttons default *
  45. * to "OK" and nothing, respectively. The hotkeys for the buttons are *
  46. * RETURN and ESCAPE. *
  47. * *
  48. * INPUT: *
  49. * msg message to display *
  50. * b1txt text for 1st button *
  51. * b2txt text for 2nd button; NULL = no 2nd button *
  52. * *
  53. * OUTPUT: *
  54. * # of button selected (0 = 1st) *
  55. * *
  56. * WARNINGS: *
  57. * 'msg' text must be <= 38 chars *
  58. * 'b1txt' and 'b2txt' must each be <= 18 chars *
  59. * *
  60. * HISTORY: *
  61. * 11/08/1994 BR : Created. *
  62. * 05/18/1995 JLB : Uses new font and dialog style. *
  63. * 08/24/1995 JLB : Handles three buttons. *
  64. *=============================================================================================*/
  65. #define BUTTON_1 1
  66. #define BUTTON_2 2
  67. #define BUTTON_3 3
  68. #define BUTTON_FLAG 0x8000
  69. int WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2txt, const char * b3txt, bool preserve)
  70. {
  71. #define BUFFSIZE (511)
  72. char buffer[BUFFSIZE];
  73. bool retval;
  74. bool process; // loop while true
  75. int selection;
  76. bool pressed;
  77. int curbutton;
  78. TextButtonClass * buttons[3];
  79. void * back;
  80. BOOL display; // display level
  81. int realval[5];
  82. #ifdef WIN32
  83. GraphicBufferClass seen_buff_save(VisiblePage.Get_Width(), VisiblePage.Get_Height(), (void*)NULL);
  84. #endif
  85. if (*b1txt == '\0') b1txt = 0;
  86. if (*b2txt == '\0') b2txt = 0;
  87. if (*b3txt == '\0') b3txt = 0;
  88. Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);
  89. /*
  90. ** Examine the optional button parameters. Fetch the width and starting
  91. ** characters for each.
  92. */
  93. int bwidth, bheight; // button width and height
  94. int numbuttons = 0;
  95. if (b1txt != NULL) {
  96. /*
  97. ** Build the button list.
  98. */
  99. bheight = FontHeight + FontYSpacing + (2 * RESFACTOR);
  100. bwidth = max((String_Pixel_Width(b1txt) + (8 * RESFACTOR)), (30 * RESFACTOR));
  101. if (b2txt != NULL) {
  102. numbuttons = 2;
  103. bwidth = max((String_Pixel_Width( b2txt ) + (8 * RESFACTOR)), bwidth);
  104. if (b3txt != NULL) {
  105. numbuttons = 3;
  106. }
  107. } else {
  108. numbuttons = 1;
  109. }
  110. }
  111. /*
  112. ** Determine the dimensions of the text to be used for the dialog box.
  113. ** These dimensions will control how the dialog box looks.
  114. */
  115. buffer[BUFFSIZE-1] = 0;
  116. strncpy(buffer, msg, BUFFSIZE-1);
  117. Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT);
  118. int width;
  119. int height;
  120. int lines = Format_Window_String(buffer, 255 * RESFACTOR, width, height);
  121. TextPrintType tpf = TPF_TEXT;
  122. width = max(width, (90 * RESFACTOR));
  123. width += 40 * RESFACTOR;
  124. height += (numbuttons == 0) ? (40 * RESFACTOR) : (60 * RESFACTOR);
  125. int x = (SeenBuff.Get_Width() - width) / 2;
  126. int y = (SeenBuff.Get_Height() - height) / 2;
  127. int printx = x + (20 * RESFACTOR);
  128. /*
  129. ** Special hack to center a one line dialog box text.
  130. */
  131. if (lines == 1) {
  132. printx = x + width/2;
  133. tpf = tpf | TPF_CENTER;
  134. }
  135. /*
  136. ** Other inits.
  137. */
  138. Set_Logic_Page(SeenBuff);
  139. #ifdef WIN32
  140. VisiblePage.Blit(seen_buff_save);
  141. #endif
  142. /*
  143. ** Initialize the button structures. All are initialized, even though one (or none) may
  144. ** actually be added to the button list.
  145. */
  146. //DOS BUILD GERMAN BUTTONS NEED TO ONE ON TOP OF THE OTHER VG 11/6/96
  147. #if (GERMAN) && (!WIN32)
  148. TextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,
  149. x + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
  150. /*
  151. ** Center button.
  152. */
  153. TextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,
  154. x + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
  155. #endif
  156. TextButtonClass button1(BUTTON_1, b1txt, TPF_BUTTON,
  157. x + ((numbuttons == 1) ? ((width - bwidth) >> 1) : (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
  158. /*
  159. ** Center button.
  160. */
  161. TextButtonClass button2(BUTTON_2, b2txt, TPF_BUTTON,
  162. x + width - (bwidth + (20 * RESFACTOR)), y + height - (bheight + (15 * RESFACTOR)), bwidth);
  163. /*
  164. ** Right button.
  165. */
  166. TextButtonClass button3(BUTTON_3, b3txt, TPF_BUTTON, 0, y + height - (bheight + (15 * RESFACTOR)));
  167. button3.X = x + ((width - button3.Width) >> 1);
  168. TextButtonClass * buttonlist = 0;
  169. curbutton = 0;
  170. /*
  171. ** Add and initialize the buttons to the button list.
  172. */
  173. memset(buttons, '\0', sizeof(buttons));
  174. if (numbuttons > 0) {
  175. buttonlist = &button1;
  176. buttons[0] = &button1;
  177. realval[0] = BUTTON_1;
  178. if (numbuttons > 2) {
  179. button3.Add(*buttonlist);
  180. buttons[1] = &button3;
  181. realval[1] = BUTTON_3;
  182. button2.Add(*buttonlist);
  183. buttons[2] = &button2;
  184. realval[2] = BUTTON_2;
  185. buttons[curbutton]->Turn_On();
  186. } else {
  187. if (numbuttons == 2) {
  188. button2.Add(*buttonlist);
  189. buttons[1] = &button2;
  190. realval[1] = BUTTON_2;
  191. buttons[curbutton]->Turn_On();
  192. }
  193. }
  194. }
  195. /*
  196. ** Draw the dialog.
  197. */
  198. Hide_Mouse();
  199. if (preserve) {
  200. back = new char[width * height];
  201. SeenBuff.To_Buffer(x, y, width, height, back, width * height);
  202. }
  203. Dialog_Box(x, y, width, height);
  204. Draw_Caption(Caption, x, y, width);
  205. /*
  206. ** Draw the body of the message.
  207. */
  208. Fancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);
  209. /*
  210. ** Redraw the buttons.
  211. */
  212. if (buttonlist) {
  213. buttonlist->Draw_All();
  214. }
  215. Show_Mouse();
  216. /*
  217. ** Main Processing Loop.
  218. */
  219. if (buttonlist) {
  220. process = true;
  221. pressed = false;
  222. while (process) {
  223. #ifdef WIN32
  224. /*
  225. ** If we have just received input focus again after running in the background then
  226. ** we need to redraw.
  227. */
  228. if (AllSurfaces.SurfacesRestored) {
  229. AllSurfaces.SurfacesRestored = false;
  230. seen_buff_save.Blit(VisiblePage);
  231. display = true;
  232. }
  233. #endif
  234. if (display) {
  235. display = false;
  236. Hide_Mouse();
  237. Dialog_Box(x, y, width, height);
  238. Draw_Caption(Caption, x, y, width);
  239. /*
  240. ** Draw the body of the message.
  241. */
  242. Fancy_Text_Print(buffer, printx, y + 20*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, tpf);
  243. /*
  244. ** Redraw the buttons.
  245. */
  246. if (buttonlist) {
  247. buttonlist->Draw_All();
  248. }
  249. Show_Mouse();
  250. }
  251. /*
  252. ** Invoke game callback.
  253. */
  254. Call_Back();
  255. /*
  256. ** Fetch and process input.
  257. */
  258. KeyNumType input = buttonlist->Input();
  259. switch (input) {
  260. case (KN_ESC):
  261. selection = realval[numbuttons-1];
  262. pressed = true;
  263. #ifdef NEVER
  264. if (numbuttons > 2) {
  265. selection = realval[1];
  266. pressed = true;
  267. } else {
  268. selection = realval[2];
  269. pressed = true;
  270. }
  271. #endif
  272. break;
  273. case (BUTTON_1|BUTTON_FLAG):
  274. selection = realval[0];
  275. pressed = true;
  276. break;
  277. case (BUTTON_2|BUTTON_FLAG):
  278. if (numbuttons > 2) {
  279. selection = realval[2];
  280. } else {
  281. selection = realval[1];
  282. }
  283. pressed = true;
  284. break;
  285. case (BUTTON_3|BUTTON_FLAG):
  286. selection = realval[1];
  287. pressed = true;
  288. break;
  289. case (KN_LEFT):
  290. if (numbuttons > 1) {
  291. buttons[curbutton]->Turn_Off();
  292. buttons[curbutton]->Flag_To_Redraw();
  293. curbutton--;
  294. if (curbutton < 0) {
  295. curbutton = numbuttons - 1;
  296. }
  297. buttons[curbutton]->Turn_On();
  298. buttons[curbutton]->Flag_To_Redraw();
  299. }
  300. break;
  301. case (KN_RIGHT):
  302. if (numbuttons > 1) {
  303. buttons[curbutton]->Turn_Off();
  304. buttons[curbutton]->Flag_To_Redraw();
  305. curbutton++;
  306. if (curbutton > (numbuttons - 1) ) {
  307. curbutton = 0;
  308. }
  309. buttons[curbutton]->Turn_On();
  310. buttons[curbutton]->Flag_To_Redraw();
  311. }
  312. break;
  313. case (KN_RETURN):
  314. selection = realval[curbutton];
  315. pressed = true;
  316. break;
  317. /*
  318. ** Check 'input' to see if it's the 1st char of button text
  319. */
  320. default:
  321. break;
  322. }
  323. if (pressed) {
  324. //#ifdef NEVER
  325. TextButtonClass * toggle;
  326. /*
  327. ** Turn all the buttons off.
  328. */
  329. toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_1);
  330. if (toggle != NULL) {
  331. toggle->Turn_Off();
  332. toggle->IsPressed = false;
  333. }
  334. toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_2);
  335. if (toggle != NULL) {
  336. toggle->Turn_Off();
  337. toggle->IsPressed = false;
  338. }
  339. toggle = (TextButtonClass *)buttonlist->Extract_Gadget(BUTTON_3);
  340. if (toggle != NULL) {
  341. toggle->Turn_Off();
  342. toggle->IsPressed = false;
  343. }
  344. //#endif
  345. /*
  346. ** Turn on and depress the button that was selected.
  347. */
  348. if (selection == BUTTON_1 || selection == BUTTON_2 || selection == BUTTON_3) {
  349. TextButtonClass * toggle = (TextButtonClass *)buttonlist->Extract_Gadget(selection);
  350. if (toggle != NULL) {
  351. // toggle->Turn_On();
  352. toggle->IsOn = true;
  353. toggle->IsPressed = true;
  354. }
  355. }
  356. Hide_Mouse();
  357. buttonlist->Draw_All(true);
  358. Show_Mouse();
  359. switch (selection) {
  360. case (BUTTON_1):
  361. retval = 0;
  362. process = false;
  363. break;
  364. case (BUTTON_2):
  365. retval = 1;
  366. process = false;
  367. break;
  368. case BUTTON_3:
  369. retval = 2;
  370. process = false;
  371. break;
  372. }
  373. pressed = false;
  374. }
  375. }
  376. } else {
  377. Keyboard->Clear();
  378. }
  379. /*
  380. ** Restore the screen if necessary.
  381. */
  382. if (preserve) {
  383. Hide_Mouse();
  384. if (SeenBuff.Lock()) {
  385. #ifdef WIN32
  386. Buffer_To_Page(x, y, width, height, back, &SeenBuff);
  387. #else
  388. MCGA_Buffer_To_Page(x, y, width, height, back, &SeenBuff);
  389. #endif
  390. }
  391. SeenBuff.Unlock();
  392. delete[] back;
  393. back = NULL;
  394. Show_Mouse();
  395. }
  396. return(retval);
  397. }
  398. /***********************************************************************************************
  399. * WWMessageBox::Process -- this one takes integer text arguments *
  400. * *
  401. * INPUT: *
  402. * msg message to display *
  403. * b1txt text for 1st button *
  404. * b2txt text for 2nd button; NULL = no 2nd button *
  405. * *
  406. * OUTPUT: *
  407. * # of button selected (0 = 1st) *
  408. * *
  409. * WARNINGS: *
  410. * 'msg' text must be <= 38 chars *
  411. * 'b1txt' and 'b2txt' must each be <= 18 chars *
  412. * *
  413. * HISTORY: *
  414. * 12/12/1994 BR : Created. *
  415. * 06/18/1995 JLB : Simplified. *
  416. *=============================================================================================*/
  417. int WWMessageBox::Process(int msg, int b1txt, int b2txt, int b3txt, bool preserve)
  418. {
  419. return(Process(Text_String(msg), b1txt, b2txt, b3txt, preserve));
  420. }
  421. /***********************************************************************************************
  422. * WWMessageBox::Process -- Displays message box. *
  423. * *
  424. * This routine will display a message box and wait for player input. It varies from the *
  425. * other message box functions only in the type of parameters it takes. *
  426. * *
  427. * INPUT: msg -- Pointer to text string for the message itself. *
  428. * *
  429. * b1txt -- Text number for the "ok" button. *
  430. * *
  431. * b2txt -- Text number for the "cancel" button. *
  432. * *
  433. * OUTPUT: Returns with the button selected. "true" if "OK" was pressed, and "false" if *
  434. * "CANCEL" was pressed. *
  435. * *
  436. * WARNINGS: none *
  437. * *
  438. * HISTORY: *
  439. * 06/18/1995 JLB : Created. *
  440. *=============================================================================================*/
  441. int WWMessageBox::Process(char const * msg, int b1txt, int b2txt, int b3txt, bool preserve)
  442. {
  443. return(Process(msg, Text_String(b1txt), Text_String(b2txt), Text_String(b3txt), preserve));
  444. }