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