EDIT.CPP 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. ** Command & Conquer(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&c\vcs\code\edit.cpv 2.18 16 Oct 1995 16:48:16 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 : EDIT.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic, Maria del Mar McCready Legg *
  28. * *
  29. * Start Date : 01/15/95 *
  30. * *
  31. * Last Update : June 25, 1995 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * EditClass::Action -- Handles input events. *
  36. * EditClass::Draw_Background -- Draw the background to the edit gadget. *
  37. * EditClass::Draw_Me -- Draws the edit box and embedded text. *
  38. * EditClass::Draw_Text -- Draws the edit gadget text. *
  39. * EditClass::EditClass -- Normal constructor for edit class object. *
  40. * EditClass::Handle_Key -- Handles keyboard input to edit gadget. *
  41. * EditClass::Set_Text -- Sets the text to the edit gadget. *
  42. * EditClass::~EditClass -- Default destructor for the edit gadget. *
  43. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  44. #include "function.h"
  45. /***********************************************************************************************
  46. * EditClass::EditClass -- Normal constructor for edit class object. *
  47. * *
  48. * This is the normal constructor used to create an edit object. *
  49. * *
  50. * INPUT: id -- The ID number for this edit object. This is the ID number that will be *
  51. * returned by the Input() function when the <RETURN> key is pressed if this *
  52. * gadget has the keyboard input focus. *
  53. * *
  54. * text -- Referenct to the text buffer that the edit gadget will modify as keyboard *
  55. * input is processed. The value that this buffer contains is the default *
  56. * text displayed. *
  57. * *
  58. * maxlen-- The maximum size of the text buffer specified. This length INCLUDES the *
  59. * trailing null character so a simple sizeof() function call can be used. *
  60. * *
  61. * flags -- These are the text print control flags. It is used to control how the *
  62. * text looks in the edit box. Use the normal TPF_??? flags. *
  63. * *
  64. * x,y -- The pixel coordinates of the upper left corner of the edit gadget area. *
  65. * *
  66. * w,h -- The pixel dimensions of the edit box. If either of these are no provided, *
  67. * or set to -1, then the dimension is determined from the string itself. *
  68. * *
  69. * sytle -- This style flag parameter control what kind of characters are allowed in *
  70. * the edit box. The initial string in the text buffer may contain illegal *
  71. * characters, but they are NOT removed regardless of this parameter. *
  72. * *
  73. * OUTPUT: none *
  74. * WARNINGS: none *
  75. * HISTORY: *
  76. * 01/05/1995 MML : Created. *
  77. * 01/21/1995 JLB : Modified. *
  78. *=============================================================================================*/
  79. EditClass::EditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w, int h, EditStyle style) :
  80. ControlClass (id, x, y, w, h, LEFTPRESS), String(text)
  81. {
  82. TextFlags = flags;
  83. EditFlags = style;
  84. Color = CC_GREEN;
  85. Set_Text(text, max_len);
  86. if (w == -1 || h == -1) {
  87. Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);
  88. if (h == -1) {
  89. Height = FontHeight+2;
  90. }
  91. if (w == -1) {
  92. if (strlen(String) > 0) {
  93. Width = String_Pixel_Width(String) + 6;
  94. } else {
  95. Width = ((Char_Pixel_Width('X')+FontXSpacing) * (MaxLength+1)) + 2;
  96. }
  97. }
  98. }
  99. IsReadOnly = 0;
  100. }
  101. /***********************************************************************************************
  102. * EditClass::~EditClass -- Default destructor for the edit gadget. *
  103. * *
  104. * This default destructor removes the focus setting if it currently has it. *
  105. * *
  106. * INPUT: none *
  107. * *
  108. * OUTPUT: none *
  109. * *
  110. * WARNINGS: none *
  111. * *
  112. * HISTORY: *
  113. * 01/24/1995 JLB : Created. *
  114. *=============================================================================================*/
  115. EditClass::~EditClass(void)
  116. {
  117. if (Has_Focus()) {
  118. Clear_Focus();
  119. }
  120. }
  121. /***********************************************************************************************
  122. * EditClass::Set_Text -- Sets the text to the edit gadget. *
  123. * *
  124. * Use this routine to change the text that this edit gadget refers to. *
  125. * *
  126. * INPUT: text -- Reference to the character array that this edit gadget will be *
  127. * modifying. *
  128. * max_len -- The maximum size of the buffer that will be modified. *
  129. * *
  130. * OUTPUT: none *
  131. * WARNINGS: none *
  132. * HISTORY: *
  133. * 01/21/1995 JLB : Created. *
  134. *=============================================================================================*/
  135. void EditClass::Set_Text(char * text, int max_len)
  136. {
  137. String = text;
  138. MaxLength = max_len-1;
  139. Length = strlen(String);
  140. Flag_To_Redraw();
  141. }
  142. /***********************************************************************************************
  143. * EditClass::Draw_Me -- Draws the edit box and embedded text. *
  144. * *
  145. * This routine will render the edit box. This will show the box outline as well as any *
  146. * text it may contain. *
  147. * *
  148. * INPUT: forced -- Should the edit box be drawn even if it thinks it doesn't have to? *
  149. * *
  150. * OUTPUT: Was the edit box drawn? *
  151. * *
  152. * WARNINGS: none *
  153. * *
  154. * HISTORY: *
  155. * 06/25/1995 JLB : Created. *
  156. *=============================================================================================*/
  157. int EditClass::Draw_Me(int forced)
  158. {
  159. if (ControlClass::Draw_Me(forced)) {
  160. /*
  161. ** Hide the mouse.
  162. */
  163. if (LogicPage == &SeenBuff) {
  164. Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
  165. }
  166. /*
  167. ** Draw the body & set text color.
  168. */
  169. Draw_Background();
  170. /*
  171. ** Display the text.
  172. */
  173. Draw_Text(String);
  174. /*
  175. ** Display the mouse.
  176. */
  177. if (LogicPage == &SeenBuff) {
  178. Conditional_Show_Mouse();
  179. }
  180. return(true);
  181. }
  182. return(false);
  183. }
  184. /***********************************************************************************************
  185. * EditClass::Action -- Handles input events. *
  186. * *
  187. * This routine will handle all mouse and keyboard events directed at this edit box *
  188. * gadget. For keyboard events, this will insert the characters into the edit box. *
  189. * *
  190. * INPUT: flags -- The event flag that triggered this function call. *
  191. * *
  192. * key -- Reference to the keyboard/mouse event that triggered this function call. *
  193. * *
  194. * OUTPUT: Should the list be processed further? *
  195. * *
  196. * WARNINGS: none *
  197. * *
  198. * HISTORY: *
  199. * 06/25/1995 JLB : Created. *
  200. *=============================================================================================*/
  201. int EditClass::Action(unsigned flags, KeyNumType & key)
  202. {
  203. /*
  204. ** If this is a read-only edit box, it's a display-only device
  205. */
  206. if (IsReadOnly) {
  207. return(false);
  208. }
  209. /*
  210. ** If the left mouse button is pressed over this gadget, then set the focus to
  211. ** this gadget. The event flag is cleared so that no button ID number is returned.
  212. */
  213. if ((flags & LEFTPRESS)) {
  214. flags &= ~LEFTPRESS;
  215. Set_Focus();
  216. Flag_To_Redraw(); // force to draw cursor
  217. }
  218. /*
  219. ** Handle keyboard events here. Normally, the key is added to the string, but if the
  220. ** RETURN key is pressed, then the button ID number is returned from the Input()
  221. ** function.
  222. */
  223. if ((flags & KEYBOARD) && Has_Focus()) {
  224. /*
  225. ** Process the keyboard character. If indicated, consume this keyboard event
  226. ** so that the edit gadget ID number is not returned.
  227. */
  228. if (key == KN_ESC) {
  229. Clear_Focus();
  230. flags = 0;
  231. } else {
  232. KeyASCIIType ascii = (KeyASCIIType)(Keyboard::To_ASCII(key) & 0x00ff);
  233. /*
  234. ** Allow numeric keypad presses to map to ascii numbers
  235. */
  236. if ((key & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9'){
  237. key &= ~WWKEY_VK_BIT;
  238. if ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))){
  239. if (Handle_Key (ascii) ) {
  240. flags &= ~KEYBOARD;
  241. key = KN_NONE;
  242. }
  243. }
  244. }else{
  245. /*
  246. ** Filter out all special keys except return and backspace
  247. */
  248. if ((!(key & WWKEY_VK_BIT) && ascii >= ' ' && ascii <= 127)
  249. || key == KN_RETURN || key == KN_BACKSPACE){
  250. if ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))){
  251. if (Handle_Key(Keyboard::To_ASCII(key))) {
  252. flags &= ~KEYBOARD;
  253. key = KN_NONE;
  254. }
  255. }
  256. }else{
  257. //if (key & WWKEY_RLS_BIT){
  258. // if ( (!(flags & LEFTRELEASE)) && (!(flags & RIGHTRELEASE))){
  259. flags &= ~KEYBOARD;
  260. key = KN_NONE;
  261. // }
  262. //}
  263. }
  264. }
  265. }
  266. }
  267. return(ControlClass::Action(flags, key));
  268. }
  269. /***********************************************************************************************
  270. * EditClass::Draw_Background -- Draw the background to the edit gadget. *
  271. * *
  272. * This routine will redraw the edit gadget background. The overlaying text is handled by *
  273. * a different routine. The mouse is guaranteed to be hidden when this routine is called. *
  274. * *
  275. * INPUT: none *
  276. * *
  277. * OUTPUT: none *
  278. * *
  279. * WARNINGS: none *
  280. * *
  281. * HISTORY: *
  282. * 01/21/1995 JLB : Created. *
  283. *=============================================================================================*/
  284. void EditClass::Draw_Background(void)
  285. {
  286. Draw_Box (X, Y, Width, Height, BOXSTYLE_GREEN_BOX, true);
  287. }
  288. /***********************************************************************************************
  289. * EditClass::Draw_Text -- Draws the edit gadget text. *
  290. * *
  291. * This routine is called when the edit gadget text needs to be drawn. The background has *
  292. * already been drawn by the time this function is called. The mouse is guaranteed to be *
  293. * hidden as well. *
  294. * *
  295. * INPUT: text -- The text to draw in the edit gadget. *
  296. * *
  297. * OUTPUT: none *
  298. * *
  299. * WARNINGS: none *
  300. * *
  301. * HISTORY: *
  302. * 01/21/1995 JLB : Created. *
  303. *=============================================================================================*/
  304. void EditClass::Draw_Text(char const * text)
  305. {
  306. if (FontPtr == GradFont6Ptr) {
  307. TextPrintType flags;
  308. if (Has_Focus()) {
  309. flags = TPF_BRIGHT_COLOR;
  310. } else {
  311. flags = (TextPrintType)0;
  312. }
  313. Conquer_Clip_Text_Print(text, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2);
  314. if (Has_Focus() && strlen(text) < MaxLength &&
  315. (String_Pixel_Width(text) + String_Pixel_Width ("_") < Width-2) ) {
  316. Conquer_Clip_Text_Print( "_", X+1+String_Pixel_Width(text), Y+1, Color, TBLACK, TextFlags | flags);
  317. }
  318. } else {
  319. Conquer_Clip_Text_Print(text, X+1, Y+1, Has_Focus() ? BLUE : WHITE, TBLACK, TextFlags, Width-2);
  320. if (Has_Focus() && strlen(text) < MaxLength &&
  321. (String_Pixel_Width(text) + String_Pixel_Width ("_") < Width-2) ) {
  322. Conquer_Clip_Text_Print("_",X+1+String_Pixel_Width(text),Y+1,BLUE,TBLACK, TextFlags);
  323. }
  324. }
  325. }
  326. /***********************************************************************************************
  327. * EditClass::Handle_Key -- Handles keyboard input to edit gadget. *
  328. * *
  329. * This is the gruntwork routine that processes keyboard input to the edit gadget. This *
  330. * routine will be called when keyboard input has been detected and this gadget has the *
  331. * current focus. *
  332. * *
  333. * INPUT: ascii -- The ASCII key code that was fetched from the keyboard buffer. *
  334. * *
  335. * OUTPUT: bool; Should this keyboard input NOT cause the gadget ID number to be returned *
  336. * from the controlling Input() routine? Typically, the return value would be *
  337. * true unless the focus is lost due to the <RETURN> key being pressed. *
  338. * *
  339. * WARNINGS: none *
  340. * HISTORY: *
  341. * 01/21/1995 JLB : Created. *
  342. *=============================================================================================*/
  343. bool EditClass::Handle_Key(KeyASCIIType ascii)
  344. {
  345. switch (ascii) {
  346. /*
  347. ** Handle the special case of a non-keyboard event. It is possible that this
  348. ** key code might be passed to this routine if this routine has been overridden
  349. ** and the key event was consumed.
  350. */
  351. case 0:
  352. break;
  353. /*
  354. ** If the return key is pressed, then remove the focus from this edit
  355. ** gadget but otherwise let the normal gadget processing proceed. This
  356. ** causes the gadget ID number to be returned from the Input() function
  357. ** so that the controlling program will know that the text can be
  358. ** processed.
  359. */
  360. case KA_RETURN:
  361. Clear_Focus();
  362. return(false);
  363. /*
  364. ** When the BACKSPACE key is pressed, remove the last character in the edit string.
  365. */
  366. case KA_BACKSPACE:
  367. if (Length) {
  368. Length--;
  369. String[Length] = '\0';
  370. Flag_To_Redraw();
  371. }
  372. break;
  373. /*
  374. ** If the keyboard event was not a recognized special key, then examine to see
  375. ** if it can legally be added to the edit string and do so if possible.
  376. */
  377. default:
  378. /*
  379. ** Don't add a character if the length is greater than edit width.
  380. */
  381. if ((String_Pixel_Width(String) + Char_Pixel_Width(ascii) ) >= (Width-2)) {
  382. break;
  383. }
  384. /*
  385. ** Don't add a character if the length is already at maximum.
  386. */
  387. if (Length >= MaxLength) break;
  388. /*
  389. ** Invisible characters are never added to the string. This is
  390. ** especially true for spaces at the beginning of the string.
  391. */
  392. if (!isgraph(ascii) && ascii != ' ') break;
  393. if (ascii == ' ' && Length == 0) break;
  394. /*
  395. ** If this is an upper case only edit gadget, then force the alphabetic
  396. ** character to upper case.
  397. */
  398. if ((EditFlags & UPPERCASE) && isalpha(ascii)) {
  399. ascii = (KeyASCIIType)toupper(ascii);
  400. }
  401. if ((!(EditFlags & NUMERIC) || !isdigit(ascii)) &&
  402. (!(EditFlags & ALPHA) || !isalpha(ascii)) &&
  403. (!(EditFlags & MISC) || isalnum(ascii)) &&
  404. ascii != ' ') {
  405. break;
  406. }
  407. /*
  408. ** The character passed all legality checks, so add it to the edit string
  409. ** and flag this gadget to be redrawn. The manual flag to redraw is needed
  410. ** because the event flag has been cleared. This prevents the gadget's ID
  411. ** number from being returned just because the gadget has been edited.
  412. */
  413. String[Length++] = ascii;
  414. String[Length] = '\0';
  415. Flag_To_Redraw();
  416. break;
  417. }
  418. return(true);
  419. }