MSGLIST.CPP 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  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. /* $Header: F:\projects\c&c\vcs\code\msglist.cpv 1.4 16 Oct 1995 16:48:20 JOE_BOSTIC $ */
  15. /***************************************************************************
  16. * *
  17. * Project Name : Command & Conquer *
  18. * *
  19. * File Name : MSGLIST.CPP *
  20. * *
  21. * Programmer : Bill R. Randolph *
  22. * *
  23. * Start Date : 05/22/95 *
  24. * *
  25. * Last Update : June 26, 1995 [BRR] *
  26. * *
  27. *-------------------------------------------------------------------------*
  28. * Functions: *
  29. * MessageListClass::Add_Edit -- Adds editable string to message list *
  30. * MessageListClass::Add_Message -- displays the given message *
  31. * MessageListClass::Draw -- Draws the messages *
  32. * MessageListClass::Get_Edit_Buf -- gets edit buffer *
  33. * MessageListClass::Init -- Inits message system, sets options *
  34. * MessageListClass::Input -- Handles input for sending messages *
  35. * MessageListClass::Manage -- Manages multiplayer messages *
  36. * MessageListClass::MessageListClass -- constructor *
  37. * MessageListClass::~MessageListClass -- destructor *
  38. * MessageListClass::Num_Messages -- returns # messages in the list *
  39. * MessageListClass::Set_Width -- sets allowable width of messages *
  40. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  41. #include "function.h"
  42. // ST = 12/17/2018 5:44PM
  43. #ifndef TickCount
  44. extern TimerClass TickCount;
  45. #endif
  46. char MessageListClass::MessageBuffers[MAX_NUM_MESSAGES][MAX_MESSAGE_LENGTH + 30];
  47. char MessageListClass::BufferAvail[MAX_NUM_MESSAGES];
  48. /***************************************************************************
  49. * MessageListClass::MessageListClass -- constructor *
  50. * *
  51. * INPUT: *
  52. * x,y coord of upper-left of top message *
  53. * max_msg max messages allowed, including edit message *
  54. * *
  55. * OUTPUT: *
  56. * none. *
  57. * *
  58. * WARNINGS: *
  59. * none. *
  60. * *
  61. * HISTORY: *
  62. * 05/21/1995 BRR : Created. *
  63. *=========================================================================*/
  64. MessageListClass::MessageListClass(void)
  65. {
  66. int i;
  67. MessageList = 0;
  68. MessageX = 0;
  69. MessageY = 0;
  70. MaxMessages = 0;
  71. MaxChars = 0;
  72. Height = 0;
  73. EditLabel = 0;
  74. EditBuf = 0;
  75. EditCurPos = 0;
  76. EditInitPos = 0;
  77. for (i = 0; i < MAX_NUM_MESSAGES; i++) {
  78. BufferAvail[i] = 1;
  79. }
  80. }
  81. /***************************************************************************
  82. * MessageListClass::~MessageListClass -- destructor *
  83. * *
  84. * INPUT: *
  85. * x,y coord of upper-left of top message *
  86. * max_msg max messages allowed, including edit message *
  87. * *
  88. * OUTPUT: *
  89. * none. *
  90. * *
  91. * WARNINGS: *
  92. * none. *
  93. * *
  94. * HISTORY: *
  95. * 05/21/1995 BRR : Created. *
  96. *=========================================================================*/
  97. MessageListClass::~MessageListClass()
  98. {
  99. Init(0,0,0,0,0);
  100. }
  101. /***************************************************************************
  102. * MessageListClass::Init -- Inits message system, sets options *
  103. * *
  104. * INPUT: *
  105. * x,y coord of upper-left of top message *
  106. * max_msg max messages allowed, including edit message *
  107. * maxchars max # characters allowed per message *
  108. * *
  109. * OUTPUT: *
  110. * none. *
  111. * *
  112. * WARNINGS: *
  113. * none. *
  114. * *
  115. * HISTORY: *
  116. * 05/21/1995 BRR : Created. *
  117. *=========================================================================*/
  118. void MessageListClass::Init(int x, int y, int max_msg, int maxchars, int height)
  119. {
  120. TextLabelClass *txtlabel;
  121. int i;
  122. /*------------------------------------------------------------------------
  123. Remove every entry in the list
  124. ------------------------------------------------------------------------*/
  125. txtlabel = MessageList;
  126. while (txtlabel) {
  127. MessageList = (TextLabelClass *)txtlabel->Remove();
  128. delete txtlabel;
  129. txtlabel = MessageList;
  130. }
  131. /*------------------------------------------------------------------------
  132. Mark all buffers as available
  133. ------------------------------------------------------------------------*/
  134. for (i = 0; i < MAX_NUM_MESSAGES; i++) {
  135. BufferAvail[i] = 1;
  136. }
  137. /*------------------------------------------------------------------------
  138. Init variables
  139. ------------------------------------------------------------------------*/
  140. MessageList = 0;
  141. MessageX = x;
  142. MessageY = y;
  143. MaxMessages = max_msg;
  144. if (MaxMessages > MAX_NUM_MESSAGES)
  145. MaxMessages = MAX_NUM_MESSAGES;
  146. MaxChars = maxchars;
  147. if (MaxChars > MAX_MESSAGE_LENGTH)
  148. MaxChars = MAX_MESSAGE_LENGTH;
  149. Height = height;
  150. EditLabel = 0;
  151. EditBuf = 0;
  152. EditCurPos = 0;
  153. EditInitPos = 0;
  154. }
  155. /***************************************************************************
  156. * MessageListClass::Add_Message -- displays the given message *
  157. * *
  158. * INPUT: *
  159. * txt text to display *
  160. * color color to draw text in *
  161. * style style to use *
  162. * timeout # of ticks the thing is supposed to last (-1 = forever)*
  163. * *
  164. * OUTPUT: *
  165. * ptr to new TextLabelClass object. *
  166. * *
  167. * WARNINGS: *
  168. * The TextLabelClass's text buffer is free'd when the class is free'd, *
  169. * so never pass it a static buffer. *
  170. * *
  171. * HISTORY: *
  172. * 05/05/1995 BRR : Created. *
  173. *=========================================================================*/
  174. TextLabelClass * MessageListClass::Add_Message(char *txt, int color,
  175. TextPrintType style, int timeout, unsigned short magic_number, unsigned short crc)
  176. {
  177. int num_msg;
  178. TextLabelClass *txtlabel;
  179. int x,y;
  180. GadgetClass *gadg;
  181. int i,j;
  182. int found;
  183. int position;
  184. char *raw_string;
  185. char *current_string;
  186. char *s1,*s2;
  187. bool same;
  188. #if (0)
  189. #if (GERMAN)
  190. static int from_adjust = -1;
  191. #else
  192. #if (FRENCH)
  193. static int from_adjust = -2;
  194. #else
  195. static int from_adjust = 0;
  196. #endif
  197. #endif
  198. #endif //(0)
  199. /*------------------------------------------------------------------------
  200. Prevent a duplicate message. (The IPXManager Global Channel cannot detect
  201. a resend of a packet, so sometimes two identical messages appear in a row.)
  202. ------------------------------------------------------------------------*/
  203. if (MessageList) {
  204. txtlabel = MessageList;
  205. while (txtlabel) {
  206. /*
  207. ** Dont check for duplicates in multi-segment strings
  208. */
  209. if (!txtlabel->Segments){
  210. if (!strcmp (txtlabel->Text,txt) && txtlabel->Color == color &&
  211. txtlabel->Style == style) {
  212. return(txtlabel);
  213. }
  214. }
  215. txtlabel = (TextLabelClass *)txtlabel->Get_Next();
  216. }
  217. }
  218. /*
  219. ** If the magic number is a valid message tail then see if we
  220. ** can add this message to the tail of an existing message (crc's must also match)
  221. */
  222. if (magic_number > MESSAGE_HEAD_MAGIC_NUMBER &&
  223. magic_number < MESSAGE_HEAD_MAGIC_NUMBER+MAX_MESSAGE_SEGMENTS){
  224. position = magic_number - MESSAGE_HEAD_MAGIC_NUMBER;
  225. txtlabel = MessageList;
  226. while (txtlabel) {
  227. if (txtlabel->Color == color && txtlabel->Style == style && txtlabel->CRC == crc) {
  228. same = true;
  229. s1 = strchr(txtlabel->Text, ':');
  230. s2 = strchr(txt, ':');
  231. if (s1 && s2){
  232. *s1 = 0;
  233. *s2 = 0;
  234. same = !strcmp (txtlabel->Text, txt);
  235. *s1 = ':';
  236. *s2 = ':';
  237. }
  238. if (same){
  239. /*
  240. ** If this message segment hasnt already come through then add it to the existing text
  241. */
  242. if (! (txtlabel->Segments & (1 << position)) ) {
  243. /*
  244. ** Search for the ':' to find the actual message after the players name
  245. */
  246. raw_string = s2;
  247. current_string = s1;
  248. if (raw_string++ && current_string++){
  249. memcpy (current_string + (position*(COMPAT_MESSAGE_LENGTH-5))/*+from_adjust*/, raw_string, COMPAT_MESSAGE_LENGTH-4);
  250. /*
  251. ** Flag this string segment as complete
  252. */
  253. txtlabel->Segments |= 1<<position;
  254. return(txtlabel);
  255. }
  256. }else{
  257. /*
  258. ** This segment has already come through for this string so discard it.
  259. */
  260. return (txtlabel);
  261. }
  262. }
  263. }
  264. txtlabel = (TextLabelClass *)txtlabel->Get_Next();
  265. }
  266. }
  267. /*------------------------------------------------------------------------
  268. Count the # of messages; if MaxMessages is going to be exceeded, remove
  269. the top-most message.
  270. ------------------------------------------------------------------------*/
  271. num_msg = 0;
  272. if (MessageList) {
  273. gadg = MessageList;
  274. while (gadg) {
  275. num_msg++;
  276. gadg = gadg->Get_Next();
  277. }
  278. }
  279. /*........................................................................
  280. Remove the top-most message, but don't remove the edit message.
  281. ........................................................................*/
  282. if ( (MaxMessages > 0) && ((num_msg + 1) > MaxMessages)) {
  283. txtlabel = MessageList;
  284. /*.....................................................................
  285. If the top label is the edit label, go to the next one; if there is
  286. no next one, just return.
  287. .....................................................................*/
  288. if (txtlabel == EditLabel)
  289. txtlabel = (TextLabelClass *)txtlabel->Get_Next();
  290. if (txtlabel==NULL)
  291. return(NULL);
  292. /*.....................................................................
  293. Remove this message from the list; mark its buffer as being available.
  294. .....................................................................*/
  295. MessageList = (TextLabelClass *)txtlabel->Remove();
  296. for (i = 0; i < MAX_NUM_MESSAGES; i++) {
  297. if (txtlabel->Text == MessageBuffers[i])
  298. BufferAvail[i] = 1;
  299. }
  300. delete txtlabel;
  301. /*.....................................................................
  302. Recompute everyone's y-coordinate
  303. .....................................................................*/
  304. y = MessageY;
  305. if (MessageList) {
  306. gadg = MessageList;
  307. while (gadg) {
  308. gadg->Y = y;
  309. gadg = gadg->Get_Next();
  310. y += Height;
  311. }
  312. }
  313. }
  314. /*------------------------------------------------------------------------
  315. Figure out the message's y-coordinate; put it below the other messages
  316. ------------------------------------------------------------------------*/
  317. x = MessageX;
  318. y = MessageY;
  319. if (MessageList) {
  320. gadg = MessageList;
  321. while (gadg) {
  322. gadg = gadg->Get_Next();
  323. y += Height;
  324. }
  325. }
  326. /*------------------------------------------------------------------------
  327. Create the message
  328. ------------------------------------------------------------------------*/
  329. txtlabel = new TextLabelClass (txt, x, y, color, style);
  330. if (timeout==-1) {
  331. txtlabel->UserData = 0;
  332. } else {
  333. txtlabel->UserData = TickCount.Time() + timeout;
  334. }
  335. /*------------------------------------------------------------------------
  336. Find a buffer to store our message in; if there are none, don't add the
  337. message.
  338. ------------------------------------------------------------------------*/
  339. found = 0;
  340. txtlabel->Segments = 0;
  341. txtlabel->CRC = crc;
  342. for (i = 0; i < MAX_NUM_MESSAGES; i++) {
  343. if (BufferAvail[i]) {
  344. BufferAvail[i] = 0;
  345. memset (MessageBuffers[i],0,MAX_MESSAGE_LENGTH + 30);
  346. strcpy (MessageBuffers[i],txt);
  347. /*
  348. ** If this is a segment from a larger message then put it in the right place
  349. ** in the buffer and clear out the rest with spaces
  350. */
  351. if (magic_number >= MESSAGE_HEAD_MAGIC_NUMBER &&
  352. magic_number < MESSAGE_HEAD_MAGIC_NUMBER+MAX_MESSAGE_SEGMENTS){
  353. raw_string = strchr(txt, ':');
  354. char *dest_str = strchr(MessageBuffers[i], ':');
  355. if (dest_str){
  356. dest_str++;
  357. }else{
  358. dest_str = MessageBuffers[i];
  359. }
  360. if (raw_string++){
  361. for (j=0 ; j<3 ; j++){
  362. if (! ((magic_number - j) == MESSAGE_HEAD_MAGIC_NUMBER)){
  363. memset (dest_str + j*(COMPAT_MESSAGE_LENGTH-4)/*+from_adjust*/, 32, COMPAT_MESSAGE_LENGTH-4);
  364. }else{
  365. strcpy(dest_str + j*(COMPAT_MESSAGE_LENGTH-4)/*+from_adjust*/, raw_string);
  366. }
  367. }
  368. *(dest_str +((COMPAT_MESSAGE_LENGTH-4)*MAX_MESSAGE_SEGMENTS-1)) = 0;
  369. }
  370. position = magic_number - MESSAGE_HEAD_MAGIC_NUMBER;
  371. txtlabel->Segments = 1<<position;
  372. }
  373. txtlabel->Text = MessageBuffers[i];
  374. found = 1;
  375. break;
  376. }
  377. }
  378. if (!found) {
  379. delete txtlabel;
  380. return (NULL);
  381. }
  382. /*------------------------------------------------------------------------
  383. Attach the message to our list
  384. ------------------------------------------------------------------------*/
  385. if (MessageList) {
  386. txtlabel->Add_Tail (*MessageList);
  387. } else {
  388. MessageList = txtlabel;
  389. }
  390. return(txtlabel);
  391. }
  392. /***************************************************************************
  393. * MessageListClass::Add_Edit -- Adds editable string to message list *
  394. * *
  395. * INPUT: *
  396. * color color of edit message *
  397. * style style of edit message *
  398. * to string: who to send to *
  399. * width width of editbox in pixels *
  400. * *
  401. * OUTPUT: *
  402. * ptr to new TextLabelClass *
  403. * *
  404. * WARNINGS: *
  405. * none. *
  406. * *
  407. * HISTORY: *
  408. * 05/22/1995 BRR : Created. *
  409. *=========================================================================*/
  410. TextLabelClass * MessageListClass::Add_Edit(int color, TextPrintType style,
  411. char *to, int width)
  412. {
  413. /*------------------------------------------------------------------------
  414. Do nothing if we're already in "edit" mode
  415. ------------------------------------------------------------------------*/
  416. if (EditLabel)
  417. return(NULL);
  418. /*------------------------------------------------------------------------
  419. Initialize the buffer positions; add a new label to the label list.
  420. ------------------------------------------------------------------------*/
  421. EditCurPos = EditInitPos = strlen(to);
  422. EditLabel = Add_Message (to, color, style, -1, 0, 0);
  423. Width = width;
  424. /*------------------------------------------------------------------------
  425. Save our edit buffer pointer.
  426. ------------------------------------------------------------------------*/
  427. if (EditLabel)
  428. EditBuf = EditLabel->Text;
  429. else
  430. EditBuf = NULL;
  431. return(EditLabel);
  432. }
  433. /***************************************************************************
  434. * MessageListClass::Get_Edit_Buf -- gets edit buffer *
  435. * *
  436. * INPUT: *
  437. * none. *
  438. * *
  439. * OUTPUT: *
  440. * ptr to edit buffer, minus the "To:" header *
  441. * *
  442. * WARNINGS: *
  443. * none. *
  444. * *
  445. * HISTORY: *
  446. * 05/21/1995 BRR : Created. *
  447. *=========================================================================*/
  448. char * MessageListClass::Get_Edit_Buf(void)
  449. {
  450. if (!EditBuf)
  451. return(NULL);
  452. return(EditBuf + EditInitPos);
  453. }
  454. /***************************************************************************
  455. * MessageListClass::Manage -- Manages multiplayer messages *
  456. * *
  457. * If this routine returns TRUE, the caller should update the display. *
  458. * *
  459. * INPUT: *
  460. * none. *
  461. * *
  462. * OUTPUT: *
  463. * none. *
  464. * *
  465. * WARNINGS: *
  466. * 0 = no change has occurred, 1 = changed *
  467. * *
  468. * HISTORY: *
  469. * 05/05/1995 BRR : Created. *
  470. *=========================================================================*/
  471. int MessageListClass::Manage (void)
  472. {
  473. TextLabelClass *txtlabel;
  474. TextLabelClass *next;
  475. int changed = 0;
  476. int y;
  477. GadgetClass *gadg;
  478. int i;
  479. /*------------------------------------------------------------------------
  480. Loop through all messages
  481. ------------------------------------------------------------------------*/
  482. txtlabel = MessageList;
  483. while (txtlabel) {
  484. /*.....................................................................
  485. If this message's time is up, remove it from the list
  486. .....................................................................*/
  487. if (txtlabel->UserData != 0 && (unsigned)TickCount.Time() > txtlabel->UserData) {
  488. /*..................................................................
  489. If we're about to delete the edit message, clear our edit message
  490. values.
  491. ..................................................................*/
  492. if (txtlabel == EditLabel) {
  493. EditLabel = 0;
  494. EditBuf = 0;
  495. }
  496. /*..................................................................
  497. Save the next ptr in the list; remove this entry
  498. ..................................................................*/
  499. next = (TextLabelClass *)txtlabel->Get_Next();
  500. MessageList = (TextLabelClass *)txtlabel->Remove();
  501. for (i = 0; i < MAX_NUM_MESSAGES; i++) {
  502. if (txtlabel->Text == MessageBuffers[i])
  503. BufferAvail[i] = 1;
  504. }
  505. delete txtlabel;
  506. changed = 1;
  507. txtlabel = next;
  508. } else {
  509. txtlabel = (TextLabelClass *)txtlabel->Get_Next();
  510. }
  511. }
  512. /*------------------------------------------------------------------------
  513. If a changed has been made, recompute the y-coord of all messages
  514. ------------------------------------------------------------------------*/
  515. if (changed) {
  516. y = MessageY;
  517. if (MessageList) {
  518. gadg = MessageList;
  519. while (gadg) {
  520. gadg->Y = y;
  521. gadg = gadg->Get_Next();
  522. y += Height;
  523. }
  524. }
  525. }
  526. return(changed);
  527. }
  528. /***************************************************************************
  529. * MessageListClass::Input -- Handles input for sending messages *
  530. * *
  531. * INPUT: *
  532. * input key value to process *
  533. * *
  534. * OUTPUT: *
  535. * 1 = caller should redraw the message list (no need to complete *
  536. * refresh, though) *
  537. * 2 = caller should completely refresh the display. *
  538. * 3 = caller should send the edit message. *
  539. * (sets 'input' to 0 if it processes it.) *
  540. * *
  541. * WARNINGS: *
  542. * none. *
  543. * *
  544. * HISTORY: *
  545. * 05/05/1995 BRR : Created. *
  546. *=========================================================================*/
  547. int MessageListClass::Input(KeyNumType &input)
  548. {
  549. KeyASCIIType ascii;
  550. int retcode = 0;
  551. /*------------------------------------------------------------------------
  552. Do nothing if nothing to do.
  553. ------------------------------------------------------------------------*/
  554. if (input == KN_NONE)
  555. return(0);
  556. /*------------------------------------------------------------------------
  557. Leave mouse events alone.
  558. ------------------------------------------------------------------------*/
  559. if ( (input & (~KN_RLSE_BIT))==KN_LMOUSE ||
  560. (input & (~KN_RLSE_BIT))==KN_RMOUSE)
  561. return(0);
  562. /*------------------------------------------------------------------------
  563. If we're in 'edit mode', handle keys
  564. ------------------------------------------------------------------------*/
  565. if (EditLabel) {
  566. ascii = (KeyASCIIType)(Keyboard::To_ASCII(input) & 0x00ff);
  567. /*
  568. ** Allow numeric keypad presses to map to ascii numbers
  569. */
  570. if ((input & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {
  571. input = (KeyNumType)(input & ~WWKEY_VK_BIT);
  572. } else {
  573. /*
  574. ** Filter out all special keys except return, escape and backspace
  575. */
  576. if ((!(input & WWKEY_VK_BIT) && !(input & KN_BUTTON)
  577. && ascii >= ' ' && ascii <= 127)
  578. || (input & 0xff)== (KN_RETURN & 0xff)
  579. || (input & 0xff)== (KN_BACKSPACE & 0xff)
  580. || (input & 0xff)== (KN_ESC & 0xff) ) {
  581. //ascii = (KeyASCIIType)(Keyboard->To_ASCII(input));
  582. } else {
  583. input = KN_NONE;
  584. return (0);
  585. }
  586. }
  587. switch (ascii) {
  588. /*------------------------------------------------------------------
  589. ESC = abort message
  590. ------------------------------------------------------------------*/
  591. case KA_ESC & 0xff:
  592. EditLabel->UserData = 1; // force it to be removed
  593. input = KN_NONE;
  594. break;
  595. /*------------------------------------------------------------------
  596. RETURN = send the message
  597. ------------------------------------------------------------------*/
  598. case KA_RETURN & 0xff:
  599. EditLabel->UserData = 1; // force it to be removed
  600. retcode = 3;
  601. input = KN_NONE;
  602. break;
  603. /*------------------------------------------------------------------
  604. BACKSPACE = remove a character
  605. ------------------------------------------------------------------*/
  606. case KA_BACKSPACE & 0xff:
  607. if (EditCurPos > EditInitPos) {
  608. EditCurPos--;
  609. EditBuf[EditCurPos] = 0;
  610. retcode = 2;
  611. }
  612. input = KN_NONE;
  613. break;
  614. /*------------------------------------------------------------------
  615. default: add a character. Reserve the last buffer position for null.
  616. (EditCurPos - EditInitPos) is the buffer index # of the next
  617. character, after the "To:" prefix.
  618. ------------------------------------------------------------------*/
  619. default:
  620. if ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {
  621. if (!(input & WWKEY_VK_BIT) && ascii >= ' ' && ascii <= 127) {
  622. EditBuf[EditCurPos] = ascii;
  623. EditCurPos++;
  624. retcode = 1;
  625. /*
  626. ** Verify that the additional character would not overrun the on screen edit box.
  627. */
  628. Fancy_Text_Print(TXT_NONE, 0, 0, EditLabel->Color, TBLACK, EditLabel->Style);
  629. int width = String_Pixel_Width(EditBuf);
  630. if (width >= Width){
  631. EditBuf[EditCurPos--] = 0;
  632. retcode = 0;
  633. }
  634. }
  635. }
  636. input = KN_NONE;
  637. break;
  638. }
  639. }
  640. return(retcode);
  641. }
  642. /***************************************************************************
  643. * MessageListClass::Draw -- draws messages *
  644. * *
  645. * INPUT: *
  646. * none *
  647. * *
  648. * OUTPUT: *
  649. * none. *
  650. * *
  651. * WARNINGS: *
  652. * none. *
  653. * *
  654. * HISTORY: *
  655. * 05/22/1995 BRR : Created. *
  656. *=========================================================================*/
  657. void MessageListClass::Draw(void)
  658. {
  659. if (MessageList) {
  660. Hide_Mouse();
  661. MessageList->Draw_All();
  662. Show_Mouse();
  663. }
  664. }
  665. /***************************************************************************
  666. * MessageListClass::Num_Messages -- returns # messages in the list *
  667. * *
  668. * INPUT: *
  669. * none. *
  670. * *
  671. * OUTPUT: *
  672. * # of messages *
  673. * *
  674. * WARNINGS: *
  675. * none. *
  676. * *
  677. * HISTORY: *
  678. * 06/26/1995 BRR : Created. *
  679. *=========================================================================*/
  680. int MessageListClass::Num_Messages(void)
  681. {
  682. GadgetClass *gadg;
  683. int num;
  684. num = 0;
  685. if (MessageList) {
  686. gadg = MessageList;
  687. while (gadg) {
  688. num++;
  689. gadg = gadg->Get_Next();
  690. }
  691. }
  692. return (num);
  693. }
  694. /***************************************************************************
  695. * MessageListClass::Set_Width -- sets allowable width of messages *
  696. * *
  697. * INPUT: *
  698. * width pixel width *
  699. * *
  700. * OUTPUT: *
  701. * none. *
  702. * *
  703. * WARNINGS: *
  704. * none. *
  705. * *
  706. * HISTORY: *
  707. * 06/26/1995 BRR : Created. *
  708. *=========================================================================*/
  709. void MessageListClass::Set_Width(int width)
  710. {
  711. GadgetClass *gadg;
  712. if (MessageList) {
  713. gadg = MessageList;
  714. while (gadg) {
  715. ((TextLabelClass *)gadg)->PixWidth = width;
  716. gadg = gadg->Get_Next();
  717. }
  718. }
  719. }