| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /CounterStrike/MSGLIST.CPP 2 3/04/97 2:52p Joe_bostic $ */
- /***************************************************************************
- *** 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 ***
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : MSGLIST.CPP *
- * *
- * Programmer : Bill R. Randolph *
- * *
- * Start Date : 05/22/95 *
- * *
- * Last Update : March 4, 1997 [JLB] *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * MessageListClass::MessageListClass -- constructor *
- * MessageListClass::~MessageListClass -- destructor *
- * MessageListClass::Init -- Inits message system, sets options *
- * MessageListClass::Add_Message -- displays the given message *
- * MessageListClass::Get_Message -- retrieves given message *
- * MessageListClass::Get_Label -- retrieves given text label *
- * MessageListClass::Concat_Message -- concats the given message *
- * MessageListClass::Add_Edit -- Adds editable string to message list *
- * MessageListClass::Remove_Edit -- removes the edit field *
- * MessageListClass::Get_Edit_Buf -- gets edit buffer *
- * MessageListClass::Set_Edit_Color -- sets color of edit gizmo *
- * MessageListClass::Manage -- Manages multiplayer messages *
- * MessageListClass::Input -- Handles input for sending messages *
- * MessageListClass::Draw -- Draws the messages *
- * MessageListClass::Num_Messages -- returns # messages in the list *
- * MessageListClass::Set_Width -- sets allowable width of messages *
- * MessageListClass::Trim_Message -- trims chars off start of message *
- * MessageListClass::Compute_Y -- recomputes y-coord for all messages *
- * MessageListClass::Reset -- Reset so no messages are visible. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- /**************************** Globals **************************************/
- /***************************************************************************
- * MessageListClass::MessageListClass -- constructor *
- * *
- * INPUT: *
- * x,y coord of upper-left of top message *
- * max_msg max messages allowed, including edit message *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/21/1995 BRR : Created. *
- *=========================================================================*/
- MessageListClass::MessageListClass(void)
- {
- int i;
- //------------------------------------------------------------------------
- // Init all data members
- //------------------------------------------------------------------------
- MessageList = 0;
- MessageX = 0;
- MessageY = 0;
- MaxMessages = 0;
- MaxChars = 0;
- Height = 0;
- EnableOverflow = 0;
- AdjustEdit = 0;
- IsEdit = 0;
- EditX = 0;
- EditY = 0;
- EditLabel = 0;
- EditBuf[0] = 0;
- OverflowBuf[0] = 0;
- EditCurPos = 0;
- EditInitPos = 0;
- CursorChar = 0;
- OverflowStart = 0;
- OverflowEnd = 0;
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- BufferAvail[i] = 1;
- }
- } // end of MessageListClass
- /***************************************************************************
- * MessageListClass::~MessageListClass -- destructor *
- * *
- * INPUT: *
- * x,y coord of upper-left of top message *
- * max_msg max messages allowed, including edit message *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/21/1995 BRR : Created. *
- *=========================================================================*/
- MessageListClass::~MessageListClass()
- {
- Init(0,0,0,0,0,0,0,0,0,0);
- } // end of ~MessageListClass
- /***************************************************************************
- * MessageListClass::Init -- Inits message system, sets options *
- * *
- * INPUT: *
- * x,y coord of upper-left of top message *
- * max_msg max messages allowed, NOT including edit message *
- * maxchars max # characters allowed per message *
- * height pixel height of a line of text *
- * edit_x x-coord of edit field; -1 = put at the top of the *
- * other messages *
- * edit_y y-coord of edit field; -1 = put at the top of the *
- * other messages *
- * overflow_on true = enable the overflow typing feature *
- * over_start start index for overflow processing *
- * over_end end index for overflow processing *
- * width pixel width of message buffer *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/21/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Init(int x, int y, int max_msg, int maxchars,
- int height, int edit_x, int edit_y, int overflow_on, int over_start,
- int over_end, int width)
- {
- TextLabelClass * txtlabel;
- int i;
- Width = width;
- //------------------------------------------------------------------------
- // Remove every entry in the list
- //------------------------------------------------------------------------
- txtlabel = MessageList;
- while (txtlabel) {
- MessageList = (TextLabelClass *)txtlabel->Remove();
- delete txtlabel;
- txtlabel = MessageList;
- }
- //------------------------------------------------------------------------
- // Mark all buffers as available
- //------------------------------------------------------------------------
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- BufferAvail[i] = 1;
- }
- //------------------------------------------------------------------------
- // Remove the editable message
- //------------------------------------------------------------------------
- if (IsEdit) {
- delete EditLabel;
- EditLabel = 0;
- }
- //------------------------------------------------------------------------
- // Init variables
- //------------------------------------------------------------------------
- MessageList = 0;
- MessageX = x;
- MessageY = y;
- MaxMessages = max_msg;
- if (MaxMessages > MAX_NUM_MESSAGES)
- MaxMessages = MAX_NUM_MESSAGES;
- MaxChars = maxchars;
- if (MaxChars > MAX_MESSAGE_LENGTH)
- MaxChars = MAX_MESSAGE_LENGTH;
- Height = height;
- //------------------------------------------------------------------------
- // Init the edit field variables. If edit_x or edit_y is -1, place the
- // edit field above the other messages; otherwise, place it at the desired
- // coords.
- //------------------------------------------------------------------------
- EnableOverflow = overflow_on;
- IsEdit = 0;
- if (edit_x == -1 || edit_y == -1) {
- AdjustEdit = 1;
- EditX = x;
- EditY = y;
- }
- else {
- AdjustEdit = 0;
- EditX = edit_x;
- EditY = edit_y;
- }
- EditLabel = 0;
- EditBuf[0] = 0;
- OverflowBuf[0] = 0;
- EditCurPos = 0;
- EditInitPos = 0;
- CursorChar = 0;
- //------------------------------------------------------------------------
- // Init the overflow processing indices
- //------------------------------------------------------------------------
- OverflowStart = over_start;
- OverflowEnd = over_end;
- if (OverflowEnd >= MaxChars) {
- OverflowEnd = MaxChars - 1;
- }
- if (OverflowStart >= OverflowEnd) {
- OverflowStart = OverflowEnd - 1;
- }
- } // end of Init
- /***********************************************************************************************
- * MessageListClass::Reset -- Reset so no messages are visible. *
- * *
- * This routine will reset the message list tracker so that any displayed messages are *
- * cleared. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 03/04/1997 JLB : Created. *
- *=============================================================================================*/
- void MessageListClass::Reset(void)
- {
- //------------------------------------------------------------------------
- // Remove every entry in the list
- //------------------------------------------------------------------------
- TextLabelClass * txtlabel = MessageList;
- while (txtlabel) {
- MessageList = (TextLabelClass *)txtlabel->Remove();
- delete txtlabel;
- txtlabel = MessageList;
- }
- //------------------------------------------------------------------------
- // Mark all buffers as available
- //------------------------------------------------------------------------
- for (int index = 0; index < MAX_NUM_MESSAGES; index++) {
- BufferAvail[index] = 1;
- }
- //------------------------------------------------------------------------
- // Remove the editable message
- //------------------------------------------------------------------------
- if (IsEdit) {
- delete EditLabel;
- EditLabel = 0;
- }
- //------------------------------------------------------------------------
- // Init variables
- //------------------------------------------------------------------------
- MessageList = 0;
- EditLabel = 0;
- IsEdit = 0;
- }
- /***************************************************************************
- * MessageListClass::Add_Message -- displays the given message *
- * *
- * INPUT: *
- * name name of sender, NULL = none *
- * id numerical ID for this message *
- * txt text to display *
- * color color to draw text in *
- * style style to use *
- * timeout # of ticks the thing is supposed to last (-1 = forever) *
- * *
- * OUTPUT: *
- * ptr to new TextLabelClass object. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/05/1995 BRR : Created. *
- * 10/16/1996 JLB : Audio feedback added. *
- *=========================================================================*/
- TextLabelClass * MessageListClass::Add_Message(char const * name, int id, char const * txt,
- PlayerColorType color, TextPrintType style, int timeout)
- {
- TextLabelClass * txtlabel;
- int i;
- int found;
- char message[MAX_MESSAGE_LENGTH + 30];
- char temp[MAX_MESSAGE_LENGTH + 30];
- int print_this_pass;
- char save = 0;
- int mess_start;
- //------------------------------------------------------------------------
- // Combine the name & message text, if there's a name given
- //------------------------------------------------------------------------
- if (name) {
- sprintf(message, "%s:%s", name, txt);
- } else {
- strcpy(message, txt);
- }
- //------------------------------------------------------------------------
- // Check that printing this wont overrun the width of the print area on screen
- //------------------------------------------------------------------------
- print_this_pass = 0;
- Fancy_Text_Print(TXT_NONE, 0, 0, &ColorRemaps[color], TBLACK, style);
- int wid = String_Pixel_Width(message);
- if (wid >= Width-8) {
- //------------------------------------------------------------------------
- // Bugger. Its too long. Loop through and find out how many chars we can print
- //------------------------------------------------------------------------
- if (name) {
- sprintf (temp, "%s:", name);
- mess_start = strlen (name)+1;
- } else {
- mess_start = 0;
- }
- for (int i=1 ; i<strlen(txt) ; i++) {
- strncpy (&temp[mess_start], txt, i);
- temp [mess_start + i] = 0;
- wid = String_Pixel_Width(temp);
- if (wid >= Width-8) {
- print_this_pass = mess_start + i-1;
- break;
- }
- }
- //------------------------------------------------------------------------
- // Prematurely terminate the string so it doesn't all print.
- // We will re-enter at the end to print the rest.
- //------------------------------------------------------------------------
- if (print_this_pass) {
- save = message [print_this_pass];
- message [print_this_pass] = 0;
- }
- }
- //------------------------------------------------------------------------
- // Remove the top-most message if we're about to exceed the max allowed
- //------------------------------------------------------------------------
- if ( (MaxMessages > 0) && ((Num_Messages() + 1) > MaxMessages)) {
- txtlabel = MessageList;
- if (txtlabel==NULL)
- return(NULL);
- //.....................................................................
- // Remove this message from the list; mark its buffer as being available.
- //.....................................................................
- MessageList = (TextLabelClass *)txtlabel->Remove();
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- if (txtlabel->Text == MessageBuffers[i])
- BufferAvail[i] = 1;
- }
- delete txtlabel;
- }
- //------------------------------------------------------------------------
- // Create the message
- //------------------------------------------------------------------------
- txtlabel = new TextLabelClass (message, MessageX, MessageY,
- &ColorRemaps[color], style);
- if (timeout==-1) {
- txtlabel->UserData1 = 0;
- }
- else {
- txtlabel->UserData1 = TickCount + timeout;
- }
- txtlabel->UserData2 = id;
- //------------------------------------------------------------------------
- // Find a buffer to store our message in; if there are none, don't add the
- // message.
- //------------------------------------------------------------------------
- found = 0;
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- if (BufferAvail[i]) {
- BufferAvail[i] = 0;
- memset (MessageBuffers[i],0,MAX_MESSAGE_LENGTH + 30);
- strcpy (MessageBuffers[i],message);
- txtlabel->Text = MessageBuffers[i];
- found = 1;
- break;
- }
- }
- if (!found) {
- delete txtlabel;
- return (NULL);
- }
- Sound_Effect(VOC_INCOMING_MESSAGE);
- //------------------------------------------------------------------------
- // Attach the message to our list
- //------------------------------------------------------------------------
- if (MessageList) {
- txtlabel->Add_Tail (*MessageList);
- }
- else {
- MessageList = txtlabel;
- }
- //------------------------------------------------------------------------
- // Recompute all messages' y-coordinate values
- //------------------------------------------------------------------------
- Compute_Y();
- //------------------------------------------------------------------------
- // If we terminated the string before the end then we need to reenter to
- // add a new message with the rest of the string.
- //------------------------------------------------------------------------
- if (save) {
- message [print_this_pass] = save;
- Add_Message (name, id, &message [print_this_pass], color, style, timeout);
- }
- return(txtlabel);
- } // end of Add_Message
- /***************************************************************************
- * MessageListClass::Get_Message -- retrieves given message *
- * *
- * INPUT: *
- * id ID of message to get *
- * *
- * OUTPUT: *
- * ptr to message text, NULL if not found *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/07/1995 BRR : Created. *
- *=========================================================================*/
- char * MessageListClass::Get_Message(int id)
- {
- TextLabelClass * gadg;
- //------------------------------------------------------------------------
- // Scan the message list, searching for the given ID
- //------------------------------------------------------------------------
- if (MessageList) {
- gadg = MessageList;
- while (gadg) {
- if (gadg->UserData2 == id) {
- return (gadg->Text);
- }
- gadg = (TextLabelClass *)gadg->Get_Next();
- }
- }
- return (NULL);
- } // end of Get_Message
- /***************************************************************************
- * MessageListClass::Get_Label -- retrieves given text label *
- * *
- * INPUT: *
- * id ID of message to get *
- * *
- * OUTPUT: *
- * ptr to message text, NULL if not found *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/07/1995 BRR : Created. *
- *=========================================================================*/
- TextLabelClass * MessageListClass::Get_Label(int id)
- {
- TextLabelClass * gadg;
- //------------------------------------------------------------------------
- // Scan the message list, searching for the given ID
- //------------------------------------------------------------------------
- if (MessageList) {
- gadg = MessageList;
- while (gadg) {
- if (gadg->UserData2 == id) {
- return (gadg);
- }
- gadg = (TextLabelClass *)gadg->Get_Next();
- }
- }
- return (NULL);
- } // end of Get_Label
- /***************************************************************************
- * MessageListClass::Concat_Message -- concats the given message *
- * *
- * INPUT: *
- * name name of sender; NULL = none *
- * id ID of message to concatenate to *
- * txt text to concatenate onto existing message *
- * timeout new timeout for message *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error (id or name not found) *
- * *
- * WARNINGS: *
- * If the required message doesn't exist, this routine does nothing. *
- * *
- * HISTORY: *
- * 11/07/1995 BRR : Created. *
- *=========================================================================*/
- int MessageListClass::Concat_Message(char const * name, int id, char const * txt, int timeout)
- {
- int min_chars;
- int max_chars;
- char * msg;
- TextLabelClass * tlabel;
- int found;
- //------------------------------------------------------------------------
- // If no name is given, or the concatenation feature is turned off,
- // don't concatenate the message
- //------------------------------------------------------------------------
- if (!name || !EnableOverflow) {
- return (0);
- }
- //------------------------------------------------------------------------
- // Scan through all active messages, searching for one with a matching
- // name & ID
- //------------------------------------------------------------------------
- found = 0;
- if (MessageList) {
- tlabel = MessageList;
- while (tlabel) {
- if (tlabel->UserData2 == id &&
- !memcmp(tlabel->Text,name,strlen(name))) {
- found = 1;
- break;
- }
- tlabel = (TextLabelClass *)tlabel->Get_Next();
- }
- }
- //------------------------------------------------------------------------
- // name and ID not found; return
- //------------------------------------------------------------------------
- if (!found) {
- return (0);
- }
- //------------------------------------------------------------------------
- // set a pointer to the text string, plus the name and colon
- //------------------------------------------------------------------------
- msg = tlabel->Text + strlen(name) + 1;
- //------------------------------------------------------------------------
- // If there's room enough in the message, just add the given string
- //------------------------------------------------------------------------
- if ( (strlen(msg) + strlen(txt)) < MaxChars) {
- //---------------------------------------------------------------------
- // We need to trim the message if there is no room to draw it
- //---------------------------------------------------------------------
- char *concat_test = new char [MaxChars+1];
- Fancy_Text_Print(TXT_NONE, 0, 0, tlabel->Color, TBLACK, tlabel->Style);
- int name_width = String_Pixel_Width(tlabel->Text) - String_Pixel_Width(msg);
- int width;
- strcpy (concat_test, msg);
- strcat (concat_test, txt);
- width = String_Pixel_Width(concat_test) + name_width;
- min_chars = 10;
- while (width >= Width-8){
- max_chars = strlen (msg);
- if (max_chars < min_chars) {
- max_chars = min_chars;
- }
- Trim_Message (NULL, msg, min_chars, max_chars, 0);
- strcpy (concat_test, msg);
- strcat (concat_test, txt);
- width = String_Pixel_Width(concat_test) + name_width;
- };
- delete [] concat_test;
- strcat (msg,txt);
- }
- //------------------------------------------------------------------------
- // Otherwise, trim off some characters from the beginning of the
- // message. Trim off at least enough to leave room for the new text.
- // Trim from left to right to remove the minimum required text.
- //------------------------------------------------------------------------
- else {
- min_chars = (strlen(msg) + strlen(txt)) - MaxChars;
- max_chars = strlen(msg);
- if (max_chars < min_chars) {
- max_chars = min_chars;
- }
- Trim_Message (NULL, msg, min_chars, max_chars, 0);
- strcat (msg, txt);
- }
- //------------------------------------------------------------------------
- // Set the new timeout value for the message
- //------------------------------------------------------------------------
- if (timeout==-1) {
- tlabel->UserData1 = 0;
- }
- else {
- tlabel->UserData1 = TickCount + timeout;
- }
- return (1);
- } // end of Concat_Message
- /***********************************************************************************************
- * MessageListClass::Set_Edit_Focus -- Give the gadget system focus to the edit box *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 10/19/96 4:41PM ST : Created *
- *=============================================================================================*/
- void MessageListClass::Set_Edit_Focus (void)
- {
- if (IsEdit) EditLabel->Set_Focus();
- }
- /***********************************************************************************************
- * MessageListClass::Has_Edit_Focus -- Find out if the edit box has the input focus *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 10/19/96 4:41PM ST : Created *
- *=============================================================================================*/
- bool MessageListClass::Has_Edit_Focus (void)
- {
- if (IsEdit){
- return (EditLabel->Has_Focus());
- }else{
- return(false);
- }
- }
- /***************************************************************************
- * MessageListClass::Add_Edit -- Adds editable string to message list *
- * *
- * INPUT: *
- * color color of edit message *
- * style style of edit message *
- * to string: who to send to; NULL = none *
- * cursor character to use as a cursor; 0 = none *
- * *
- * OUTPUT: *
- * ptr to new TextLabelClass *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/22/1995 BRR : Created. *
- *=========================================================================*/
- TextLabelClass * MessageListClass::Add_Edit(PlayerColorType color,
- TextPrintType style, char * to, char cursor, int width)
- {
- int i;
- TextLabelClass * txtlabel;
- //------------------------------------------------------------------------
- // Do nothing if we're already in "edit" mode
- //------------------------------------------------------------------------
- if (IsEdit) {
- EditLabel->Set_Focus();
- return(NULL);
- }
- //------------------------------------------------------------------------
- // Remove the top-most message if we're about to exceed the max allowed
- //------------------------------------------------------------------------
- if (AdjustEdit && ((Num_Messages() + 1) > MaxMessages)) {
- txtlabel = MessageList;
- MessageList = (TextLabelClass *)txtlabel->Remove();
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- if (txtlabel->Text == MessageBuffers[i])
- BufferAvail[i] = 1;
- }
- delete txtlabel;
- }
- //------------------------------------------------------------------------
- // If no 'to' field was passed in, ignore it
- //------------------------------------------------------------------------
- if (!to) {
- to = "";
- }
- //------------------------------------------------------------------------
- // Set the cursor character
- //------------------------------------------------------------------------
- CursorChar = cursor;
- //------------------------------------------------------------------------
- // Initialize the buffer positions; create a new text label object
- //------------------------------------------------------------------------
- memset (EditBuf, 0, sizeof(EditBuf));
- strcpy (EditBuf, to);
- OverflowBuf[0] = 0;
- EditCurPos = EditInitPos = strlen(to);
- EditLabel = new TextLabelClass (EditBuf, EditX, EditY,
- &ColorRemaps[color], style);
- Width = width;
- if (EditLabel) {
- IsEdit = 1;
- EditLabel->Set_Focus();
- }
- else {
- IsEdit = 0;
- }
- //------------------------------------------------------------------------
- // If the edit field appears over the message list, recompute the y-value
- // for all messages. Also, adjust MaxMessages down by one, since there
- // is now one less slot available.
- //------------------------------------------------------------------------
- if (AdjustEdit) {
- Compute_Y();
- MaxMessages--;
- }
- return(EditLabel);
- } // end of Add_Edit
- /***************************************************************************
- * MessageListClass::Remove_Edit -- removes the edit field *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/06/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Remove_Edit(void)
- {
- //------------------------------------------------------------------------
- // If the edit field is active, delete it
- //------------------------------------------------------------------------
- if (IsEdit) {
- IsEdit = 0;
- delete EditLabel;
- //.....................................................................
- // If the edit field appears over the message list, recompute the
- // y-value for all messages. Adjust MaxMessages back up, since there
- // is now a new available slot.
- //.....................................................................
- if (AdjustEdit) {
- Compute_Y();
- MaxMessages++;
- }
- }
- } // end if Remove_Edit
- /***************************************************************************
- * MessageListClass::Get_Edit_Buf -- gets edit buffer *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * ptr to edit buffer, minus the "To:" header *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/21/1995 BRR : Created. *
- *=========================================================================*/
- char * MessageListClass::Get_Edit_Buf(void)
- {
- return(EditBuf + EditInitPos);
- } // end of Get_Edit_Buf
- /***************************************************************************
- * MessageListClass::Set_Edit_Color -- sets color of edit gizmo *
- * *
- * INPUT: *
- * color color to set edit label to *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/08/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Set_Edit_Color(PlayerColorType color)
- {
- if (IsEdit) {
- EditLabel->Color = &ColorRemaps[color];
- }
- } // end of Set_Edit_Color
- /***************************************************************************
- * MessageListClass::Manage -- Manages multiplayer messages *
- * *
- * If this routine returns TRUE, the caller should update the display. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * 0 = no change has occurred, 1 = changed *
- * *
- * HISTORY: *
- * 05/05/1995 BRR : Created. *
- *=========================================================================*/
- int MessageListClass::Manage (void)
- {
- TextLabelClass * txtlabel;
- TextLabelClass * next;
- int changed = 0;
- int i;
- //------------------------------------------------------------------------
- // Loop through all messages
- //------------------------------------------------------------------------
- txtlabel = MessageList;
- while (txtlabel) {
- //.....................................................................
- // If this message's time is up, remove it from the list
- //.....................................................................
- if (txtlabel->UserData1 != 0 && TickCount > txtlabel->UserData1) {
- //..................................................................
- // Save the next ptr in the list; remove this entry
- //..................................................................
- next = (TextLabelClass *)txtlabel->Get_Next();
- MessageList = (TextLabelClass *)txtlabel->Remove();
- for (i = 0; i < MAX_NUM_MESSAGES; i++) {
- if (txtlabel->Text == MessageBuffers[i]) {
- BufferAvail[i] = 1;
- }
- }
- delete txtlabel;
- changed = 1;
- txtlabel = next;
- }
- else {
- txtlabel = (TextLabelClass *)txtlabel->Get_Next();
- }
- }
- //------------------------------------------------------------------------
- // If a changed has been made, recompute the y-coord of all messages
- //------------------------------------------------------------------------
- if (changed) {
- Compute_Y();
- }
- return(changed);
- } // end of Manage
- /***************************************************************************
- * MessageListClass::Input -- Handles input for sending messages *
- * *
- * INPUT: *
- * input key value to process *
- * *
- * OUTPUT: *
- * 1 = caller should redraw the message list (no need to complete *
- * refresh, though) *
- * 2 = caller should completely refresh the display. *
- * 3 = caller should send the edit message. *
- * (sets 'input' to 0 if it processes it.) *
- * 4 = caller should send the Overflow buffer *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/05/1995 BRR : Created. *
- *=========================================================================*/
- int MessageListClass::Input(KeyNumType &input)
- {
- KeyASCIIType ascii;
- int retcode = 0;
- int numchars;
- //------------------------------------------------------------------------
- // Do nothing if nothing to do.
- //------------------------------------------------------------------------
- if (input == KN_NONE) {
- return(0);
- }
- //------------------------------------------------------------------------
- // Leave mouse events alone.
- //------------------------------------------------------------------------
- if ( (input & (~KN_RLSE_BIT))==KN_LMOUSE ||
- (input & (~KN_RLSE_BIT))==KN_RMOUSE) {
- return(0);
- }
- //------------------------------------------------------------------------
- // If we're in 'edit mode', handle keys
- //------------------------------------------------------------------------
- if (IsEdit) {
- ascii = (KeyASCIIType)(Keyboard->To_ASCII(input) & 0x00ff);
- #ifdef WIN32
- /*
- ** Allow numeric keypad presses to map to ascii numbers
- */
- if ((input & WWKEY_VK_BIT) && ascii >='0' && ascii <= '9') {
- input = (KeyNumType)(input & ~WWKEY_VK_BIT);
- } else {
- /*
- ** Filter out all special keys except return, escape and backspace
- */
- if ((!(input & WWKEY_VK_BIT) && !(input & KN_BUTTON)
- && ascii >= ' ' && ascii <= 127)
- || (input & 0xff)== (KN_RETURN & 0xff)
- || (input & 0xff)== (KN_BACKSPACE & 0xff)
- || (input & 0xff)== (KN_ESC & 0xff) ) {
- //ascii = (KeyASCIIType)(Keyboard->To_ASCII(input));
- } else {
- input = KN_NONE;
- return (0);
- }
- }
- #endif //WIN32
- switch (ascii) {
- //..................................................................
- // ESC = abort message
- //..................................................................
- case KA_ESC & 0xff:
- Remove_Edit();
- retcode = 2;
- input = KN_NONE;
- break;
- //..................................................................
- // RETURN = send the message.
- // Add a space to the end, in case another message gets concatenated
- // onto this one after we send it; then, they won't be mushed
- // together.
- //..................................................................
- case KA_RETURN & 0xff:
- if (EditCurPos == EditInitPos) {
- retcode = 0;
- input = KN_NONE;
- break;
- }
- if ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {
- EditBuf[EditCurPos] = ' ';
- EditCurPos++;
- EditBuf[EditCurPos] = 0;
- }
- Remove_Edit();
- retcode = 3;
- input = KN_NONE;
- break;
- //..................................................................
- // BACKSPACE = remove a character
- //..................................................................
- case KA_BACKSPACE & 0xff:
- if (EditCurPos > EditInitPos) {
- EditCurPos--;
- EditBuf[EditCurPos] = 0;
- retcode = 2;
- }
- input = KN_NONE;
- EditLabel->Set_Focus();
- break;
- //..................................................................
- // default: add a character. Reserve the last buffer position for
- // null. (EditCurPos - EditInitPos) is the buffer index # of the
- // next character, after the "To:" prefix.
- //..................................................................
- default:
- EditLabel->Set_Focus();
- bool overflowed = false;
- if (ascii >= ' ' && ascii <= 127) {
- if ( (EditCurPos - EditInitPos) < (MaxChars - 1) ) {
- EditBuf[EditCurPos] = ascii;
- EditCurPos++;
- EditBuf[EditCurPos] = 0;
- retcode = 1;
- /*
- ** Verify that the additional character would not overrun the on screen edit box.
- */
- Fancy_Text_Print(TXT_NONE, 0, 0, EditLabel->Color, TBLACK, EditLabel->Style);
- int width = String_Pixel_Width(EditBuf);
- if (width >= Width-10) {
- overflowed = true;
- EditCurPos--;
- EditBuf[EditCurPos] = 0;
- retcode = 0;
- }
- } else {
- //............................................................
- // If there's no room in the buffer, and overflow is enabled,
- // trim the extra characters off (from right to left, to
- // remove the max possible characters), and then add the new
- // character in.
- //............................................................
- overflowed = true;
- }
- if (/*BGEnableOverflow &&*/ overflowed) {
- numchars = Trim_Message (OverflowBuf, EditBuf + EditInitPos,
- OverflowStart,OverflowEnd, 1);
- EditCurPos -= numchars;
- EditBuf[EditCurPos] = ascii;
- EditCurPos++;
- EditBuf[EditCurPos] = 0;
- retcode = 4;
- }
- }
- input = KN_NONE;
- break;
- }
- }
- return(retcode);
- } // end of Input
- /***************************************************************************
- * MessageListClass::Draw -- draws messages *
- * *
- * INPUT: *
- * none *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/22/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Draw(void)
- {
- char txt[2] = {0,0};
- if (IsEdit) {
- if (LogicPage == &SeenBuff) {
- Hide_Mouse();
- }
- EditLabel->Draw_Me(true);
- if (CursorChar && (EditCurPos - EditInitPos) < (MaxChars - 1) && EditLabel->Has_Focus()) {
- txt[0] = CursorChar;
- Fancy_Text_Print(txt,
- EditLabel->X + String_Pixel_Width(EditLabel->Text),
- EditLabel->Y,
- EditLabel->Color,
- TBLACK,
- EditLabel->Style);
- }
- if (LogicPage == &SeenBuff) {
- Show_Mouse();
- }
- }
- if (MessageList) {
- if (LogicPage == &SeenBuff) {
- Hide_Mouse();
- }
- MessageList->Draw_All();
- if (LogicPage == &SeenBuff) {
- Show_Mouse();
- }
- }
- } // end of Draw
- /***************************************************************************
- * MessageListClass::Num_Messages -- returns # messages in the list *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * # of messages, including the edit field if it's above the messages *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/26/1995 BRR : Created. *
- *=========================================================================*/
- int MessageListClass::Num_Messages(void)
- {
- GadgetClass * gadg;
- int num;
- num = 0;
- if (MessageList) {
- gadg = MessageList;
- while (gadg) {
- num++;
- gadg = gadg->Get_Next();
- }
- }
- if (IsEdit && AdjustEdit) {
- num++;
- }
- return (num);
- } // end of Num_Messages
- /***************************************************************************
- * MessageListClass::Set_Width -- sets allowable width of messages *
- * *
- * INPUT: *
- * width pixel width *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/26/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Set_Width(int width)
- {
- GadgetClass * gadg;
- if (MessageList) {
- gadg = MessageList;
- while (gadg) {
- ((TextLabelClass *)gadg)->PixWidth = width;
- gadg = gadg->Get_Next();
- }
- }
- if (IsEdit) {
- EditLabel->PixWidth = width;
- }
- } // end of Set_Width
- /***************************************************************************
- * MessageListClass::Trim_Message -- trims chars off start of message *
- * *
- * INPUT: *
- * dest buffer to store removed characters in; NULL = none *
- * src text buffer to trim *
- * min_chars min # chars that must be trimmed off *
- * max_chars max # chars allowed to trim *
- * scandir 0 = left-to-right, 1 = right-to-left *
- * *
- * OUTPUT: *
- * # characters removed *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/07/1995 BRR : Created. *
- *=========================================================================*/
- int MessageListClass::Trim_Message(char * dest, char * src, int min_chars,
- int max_chars, int scandir)
- {
- int i;
- int len;
- int found;
- //------------------------------------------------------------------------
- // validate parameters
- //------------------------------------------------------------------------
- if (min_chars <= 0) {
- return(0);
- }
- len = strlen (src);
- if (max_chars > len) {
- max_chars = len;
- }
- //------------------------------------------------------------------------
- // find 1st available white space; if there is none, just trim off
- // 'min_chars' characters. 'i' will be the number of chars to trim.
- // The chars removed will include the white space.
- //------------------------------------------------------------------------
- found = 0;
- //........................................................................
- // scan from left to right
- //........................................................................
- if (scandir == 0) {
- for (i = min_chars; i <= max_chars; i++) {
- if (isspace(src[i - 1])) {
- found = 1;
- break;
- }
- }
- }
- //........................................................................
- // scan from right to left
- //........................................................................
- else {
- for (i = max_chars; i >= min_chars; i--) {
- if (isspace(src[i - 1])) {
- found = 1;
- break;
- }
- }
- }
- //........................................................................
- // If no whitespace was found, just set 'i' to the min # characters
- //........................................................................
- if (!found) {
- i = min_chars;
- }
- //------------------------------------------------------------------------
- // Save trimmed characters in the dest buffer, if there is one
- //------------------------------------------------------------------------
- if (dest) {
- memcpy (dest, src, i);
- dest[i] ='\0';
- }
- //------------------------------------------------------------------------
- // Shift characters over in the source buffer
- //------------------------------------------------------------------------
- memmove (src, src + i, len - i + 1);
- return (i);
- } // end of Trim_Message
- /***************************************************************************
- * MessageListClass::Compute_Y -- recomputes y-coord for all messages *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/07/1995 BRR : Created. *
- *=========================================================================*/
- void MessageListClass::Compute_Y(void)
- {
- GadgetClass * gadg;
- int y;
- //------------------------------------------------------------------------
- // If the editable message is attached to the message list, 'AdjustEdit'
- // will be set; so, adjust all y-values downward one line. Otherwise,
- // the editable message has its own screen coordinates.
- //------------------------------------------------------------------------
- if (IsEdit && AdjustEdit) {
- y = MessageY + Height;
- }
- else {
- y = MessageY;
- }
- if (MessageList) {
- gadg = MessageList;
- while (gadg) {
- gadg->Y = y;
- gadg = gadg->Get_Next();
- y += Height;
- }
- }
- } // end of Compute_Y
- /*************************** end of msglist.cpp ****************************/
|