From: <Kha...@us...> - 2009-11-29 03:20:24
|
Revision: 4818 http://planeshift.svn.sourceforge.net/planeshift/?rev=4818&view=rev Author: Khakilord Date: 2009-11-29 03:20:16 +0000 (Sun, 29 Nov 2009) Log Message: ----------- Compressed format of colour coding to be compatible with UTF-8. Added support for mid-line colour changes in only pawsMessageTextBox for now. Added colouring to a few basic chat types such as /say. Fixed some colour escaping issues. Added highlighting when player's name is mentioned. TODO: Filter colours on user input server side. Modified Paths: -------------- trunk/src/client/gui/chatwindow.cpp trunk/src/common/paws/pawstextbox.cpp trunk/src/common/paws/pawstextbox.h Modified: trunk/src/client/gui/chatwindow.cpp =================================================================== --- trunk/src/client/gui/chatwindow.cpp 2009-11-28 23:17:53 UTC (rev 4817) +++ trunk/src/client/gui/chatwindow.cpp 2009-11-29 03:20:16 UTC (rev 4818) @@ -1285,6 +1285,18 @@ // Use lowercase strings csString noCasePerson = msg.sPerson; noCasePerson.Downcase(); + + bool hasCharName = noCasePerson.Find(noCasePlayerForename) != (size_t)-1; + + csString noCaseText = msg.sText; + noCaseText.Downcase(); + size_t charNamePos = noCaseText.Find(noCasePlayerForename); + if(charNamePos != (size_t) -1) + { + msg.sText.Insert(charNamePos, REDCODE); + msg.sText.Insert(charNamePos + 5 + noCasePlayerForename.Length(), DEFAULTCODE); + } + csString noCaseMsg = msg.sText; noCaseMsg.Downcase(); @@ -1301,21 +1313,21 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s says: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("says"), + (const char *)msg.sText); colour = settings.groupColor; break; } case CHAT_SHOUT: { - buff.Format(PawsManager::GetSingleton().Translate("%s shouts: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("shouts"), + (const char *)msg.sText); colour = settings.shoutColor; break; } case CHAT_GM: { - buff.Format(PawsManager::GetSingleton().Translate("%s"), (const char *)msg.sText); + buff.Format("%s", (const char *)msg.sText); colour = settings.gmColor; break; } @@ -1328,8 +1340,8 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s says: %s"), - (const char *)msg.sPerson,(const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("says:"), + (const char *)msg.sText); colour = settings.guildColor; break; } @@ -1342,8 +1354,8 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s says: %s"), - (const char *)msg.sPerson,(const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("says"), + (const char *)msg.sText); colour = settings.allianceColor; break; } @@ -1355,8 +1367,8 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s auctions: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("auctions"), + (const char *)msg.sText); colour = settings.auctionColor; break; } @@ -1368,8 +1380,14 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s says: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + { + if(hasCharName) + buff.Format(REDCODE "%s" DEFAULTCODE " %s: %s", (const char *)msg.sPerson, (const char *) PawsManager::GetSingleton().Translate("says"), + (const char *)msg.sText); + else + buff.Format(GREENCODE "%s" DEFAULTCODE " %s: %s", (const char *)msg.sPerson, (const char *) PawsManager::GetSingleton().Translate("says"), + (const char *)msg.sText); + } colour = settings.chatColor; break; } @@ -1377,8 +1395,8 @@ case CHAT_NPCINTERNAL: case CHAT_NPC: { - buff.Format(PawsManager::GetSingleton().Translate("%s says: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + buff.Format(BLUECODE "%s" DEFAULTCODE " %s: %s", + (const char *)msg.sPerson, (const char *) PawsManager::GetSingleton().Translate("says"), (const char *)msg.sText); colour = settings.npcColor; break; } @@ -1441,8 +1459,8 @@ else if ( msg.sText.StartsWith("/my ") ) buff.Format("%s's %s", (const char *)msg.sPerson, ((const char *)msg.sText)+4); else - buff.Format(PawsManager::GetSingleton().Translate("%s tells you: %s"), - (const char *)msg.sPerson, (const char *)msg.sText); + buff.Format("%s %s: %s", (const char *)msg.sPerson, (const char *)PawsManager::GetSingleton().Translate("tells you"), + (const char *)msg.sText); colour = settings.tellColor; break; @@ -1462,7 +1480,7 @@ ((const char *)msg.sText)+4); } else - buff.Format(PawsManager::GetSingleton().Translate("You tell %s: %s"), + buff.Format("%s %s: %s", (const char *)PawsManager::GetSingleton().Translate("You tell"), (const char *)msg.sPerson, (const char *)msg.sText); if (IgnoredList->IsIgnored(msg.sPerson)) @@ -1560,13 +1578,17 @@ } } - WordArray playerName(psengine->GetMainPlayerName()); - bool hasCharName = msg.sText.Downcase().Find(playerName[0].Downcase().GetData()) != (size_t)-1; + if (!buff.IsEmpty()) { ChatOutput(buff.GetData(), colour, msg.iChatType, flashEnabled, hasCharName, channelID); } + + // Remove colour codes for log + size_t colourStart = buff.FindFirst(1); + while(colourStart != (size_t) -1 && colourStart + 4 < buff.Length()) + buff.DeleteAt(colourStart, 5); LogMessage(CHAT_LOG_ALL, buff.GetDataSafe(), msg.iChatType); Modified: trunk/src/common/paws/pawstextbox.cpp =================================================================== --- trunk/src/common/paws/pawstextbox.cpp 2009-11-28 23:17:53 UTC (rev 4817) +++ trunk/src/common/paws/pawstextbox.cpp 2009-11-29 03:20:16 UTC (rev 4818) @@ -393,9 +393,20 @@ CalcLineHeight(); adjusted.Empty(); + for ( size_t x = 0; x < messages.GetSize(); x++ ) { - SplitMessage( messages[x]->text, messages[x]->colour, messages[x]->size ); + MessageLine* dummy = NULL; + int dummyX = -1; + if(messages[x]->segments.IsEmpty()) + SplitMessage( messages[x]->text, messages[x]->colour, messages[x]->size, dummy, dummyX ); + else + { + MessageLine* msgLine = NULL; + int offsetX = 0; + for(size_t i = 0; i < messages[x]->segments.GetSize(); i++) + SplitMessage( messages[x]->segments[i].text, messages[x]->segments[i].colour, messages[x]->segments[i].size, msgLine, offsetX); + } } } @@ -447,27 +458,44 @@ { if ( x < adjusted.GetSize() ) { - //int oldSize = GetFont()->GetSize(); - if(adjusted[x]->size) - { - //ChangeFontSize(adjusted[x]->size); - } - // Draw shadow - graphics2D->Write( GetFont(), - screenFrame.xmin + 1, - screenFrame.ymin + yPos*lineHeight + 1, - 0, - -1, - (const char*)adjusted[x]->text ); - // Draw actual text - graphics2D->Write( GetFont(), - screenFrame.xmin, - screenFrame.ymin + yPos*lineHeight, - adjusted[x]->colour, - -1, - (const char*)adjusted[x]->text ); + if(adjusted[x]->segments.IsEmpty()) + { + // Draw shadow + graphics2D->Write( GetFont(), + screenFrame.xmin + 1, + screenFrame.ymin + yPos*lineHeight + 1, + 0, + -1, + (const char*)adjusted[x]->text ); + // Draw actual text + graphics2D->Write( GetFont(), + screenFrame.xmin, + screenFrame.ymin + yPos*lineHeight, + adjusted[x]->colour, + -1, + (const char*)adjusted[x]->text ); + } + else + { + for(size_t i = 0; i < adjusted[x]->segments.GetSize(); i++) + { + // Draw shadow + graphics2D->Write( GetFont(), + screenFrame.xmin + adjusted[x]->segments[i].x + 1, + screenFrame.ymin + yPos*lineHeight + 1, + 0, + -1, + (const char*)adjusted[x]->segments[i].text ); + // Draw actual text + graphics2D->Write( GetFont(), + screenFrame.xmin + adjusted[x]->segments[i].x, + screenFrame.ymin + yPos*lineHeight, + adjusted[x]->segments[i].colour, + -1, + (const char*)adjusted[x]->segments[i].text ); + } + } - //ChangeFontSize(oldSize); yPos++; } } @@ -544,36 +572,69 @@ int colour = msgColour; int size = 0; - // 1 is a control character which should be filtered out of user text input. - // Format is 5 bytes. - // 1st byte is 1 which is the control character - // 2nd is R value - // 3rd is G value - // 4th is B value - // 5th is text size - // A value of 1 means that property should not be set. - size_t pos = messageText.FindFirst(1); - if(pos != (size_t)-1 && pos + 5 < messageText.Length()) + if(msgColour == -1) { - if(messageText[pos + 1] != 1 || messageText[pos + 2] != 1 || messageText[pos + 3] != 1) - colour = graphics2D->FindRGB(messageText[pos + 1], messageText[pos + 2], messageText[pos + 3]); - if(messageText[pos + 4] != 1) - size = messageText[pos + 4]; - messageText = messageText.DeleteAt(pos, 5); - } - else if(msgColour == -1) - { colour = GetFontColour(); } - - msg->size = size; - msg->colour = colour; + + size_t textStart = 0; + size_t textEnd = messageText.Length(); + int x = 0; + MessageLine* msgLine = NULL; + msg->size = 0; + msg->colour = msgColour; msg->text = messageText; - messages.Push(msg); - SplitMessage( messageText, colour, size ); - + while(textStart < messageText.Length()) + { + // 1 is a control character which should be filtered out of user text input. + // The code is 5 bytes. + // 1st byte is 1 which is the control character + // 2nd is R value / 2 + // 3rd is G value / 2 + // 4th is B value / 2 + // 5th is text size + // A value of 1 in all colours or in text size means that field should not be set. + size_t pos = messageText.FindFirst(1, textStart); + if(pos == (size_t) - 1) + textEnd = messageText.Length(); + else + textEnd = pos; + + if(textStart == 0 && pos == (size_t) - 1) + { + int dummyX = -1; + SplitMessage( messageText, colour, size, msgLine, dummyX); + break; + } + else if(textEnd > textStart) + { + csString subText = messageText.Slice(textStart, textEnd - textStart); + SplitMessage( subText, colour, size, msgLine, x); + + MessageSegment newSegment; + newSegment.text = subText; + newSegment.colour = colour; + newSegment.size = size; + msg->segments.Push(newSegment); + } + textStart = textEnd; + + if(pos != (size_t)-1 && pos + 4 < messageText.Length()) + { + if(messageText[pos + 1] != 1 || messageText[pos + 2] != 1 || messageText[pos + 3] != 1) + colour = graphics2D->FindRGB((unsigned char)messageText[pos + 1] * 2, (unsigned char)messageText[pos + 2] * 2, (unsigned char)messageText[pos + 3] * 2); + else + colour = msgColour; + if(messageText[pos + 4] != 1) + size = messageText[pos + 4]; + else + size = 0; + messageText.DeleteAt(pos, 5); + } + } + messages.Push(msg); if (scrollBar) { if ( adjusted.GetSize() > maxLines ) @@ -648,14 +709,16 @@ } -void pawsMessageTextBox::SplitMessage( const char* newText, int colour, int size ) +void pawsMessageTextBox::SplitMessage( const char* newText, int colour, int size, MessageLine*& msgLine, int& x) { if(!newText) return; if(strlen(newText) == 0) { - MessageLine* msgLine = new MessageLine; + if(x > 0) + return; + msgLine = new MessageLine; msgLine->size = size; msgLine->text = newText; msgLine->colour = colour; @@ -663,37 +726,48 @@ } else if (newText[0] != '\0') { - int maxWidth; - int maxHeight; - - //int oldSize = GetFont()->GetSize(); - if(size) - { - //ChangeFontSize(size); - } - GetFont()->GetMaxSize( maxWidth, maxHeight ); char* dummy = new char[strlen( newText ) + 1]; char* head = dummy; strcpy( dummy, newText ); - - int offSet = 40; - + while ( dummy ) { - /// See how many characters can be drawn on a single line. + int offSet = 20; + int width = -1; + int height = -1; + /// See how many characters can be drawn on a single line. + if (x != -1) + { + GetFont()->GetDimensions(dummy, width, height); + offSet += x; + } int canDrawLength = GetFont()->GetLength( dummy, screenFrame.Width()-offSet ); CS_ASSERT_MSG("iFont->GetLength returned 0. Infinite loop detected.", canDrawLength != 0); /// If it can fit the entire string then return. if ( canDrawLength == (int)strlen( dummy ) ) { - MessageLine* msgLine = new MessageLine; - msgLine->size = size; - msgLine->text = dummy; - msgLine->colour = colour; - adjusted.Push( msgLine ); + if(!msgLine) + { + msgLine = new MessageLine; + msgLine->size = size; + msgLine->text = dummy; + msgLine->colour = colour; + adjusted.Push( msgLine ); + } + if(x != -1) + { + MessageSegment seg; + seg.size = size; + seg.text = dummy; + seg.colour = colour; + seg.x = x; + msgLine->text.Clear(); + msgLine->segments.Push(seg); + x += width; + } break; } // We have to push in a new line to the lines bit. @@ -715,11 +789,26 @@ csString test; test.Append( dummy, index ); dummy+=index; - MessageLine* msgLine = new MessageLine; - msgLine->size = size; - msgLine->text = test; - msgLine->colour = colour; - adjusted.Push( msgLine ); + if(!msgLine) + { + msgLine = new MessageLine; + msgLine->size = size; + msgLine->text = test; + msgLine->colour = colour; + adjusted.Push( msgLine ); + } + if(x != -1) + { + MessageSegment seg; + seg.size = size; + seg.text = test; + seg.colour = colour; + seg.x = x; + msgLine->segments.Push(seg); + x = 0; + } + // Next time use a new line! + msgLine = NULL; } } Modified: trunk/src/common/paws/pawstextbox.h =================================================================== --- trunk/src/common/paws/pawstextbox.h 2009-11-28 23:17:53 UTC (rev 4817) +++ trunk/src/common/paws/pawstextbox.h 2009-11-29 03:20:16 UTC (rev 4818) @@ -29,6 +29,22 @@ #include <csutil/parray.h> #include <ivideo/fontserv.h> +// 1 is a control character which should be filtered out of user text input. +// The code is 5 bytes. +// 1st byte is 1 which is the control character +// 2nd is R value / 2 +// 3rd is G value / 2 +// 4th is B value / 2 +// 5th is text size +// A value of 1 in all colours or in text size means that field should not be set. + +// Shortcut 5-byte color/size codes +// Divide the rgb value / 2 (to prevent conflicts with UTF8) +#define REDCODE "\x01\x7f\x01\x01\x01" +#define GREENCODE "\x01\x01\x7f\x01\x01" +#define BLUECODE "\x01\x01\x01\x7f\x01" +#define DEFAULTCODE "\x01\x01\x01\x01\x01" + /** A basic text box widget. */ class pawsTextBox : public pawsWidget @@ -131,11 +147,21 @@ class pawsMessageTextBox : public pawsWidget { public: + struct MessageSegment + { + int x; + csString text; + int colour; + int size; + + MessageSegment() : x(0), text(""), colour(0), size(0) { } + }; struct MessageLine { csString text; int colour; int size; + csArray<MessageSegment> segments; MessageLine() { @@ -184,6 +210,7 @@ void FullScroll(); virtual void OnUpdateData(const char *dataname,PAWSData& data); + protected: /// Renders an entire message and returns the total lines it took. @@ -194,7 +221,7 @@ //void AdjustMessages(); - void SplitMessage( const char* newText, int colour, int size ); + void SplitMessage( const char* newText, int colour, int size, MessageLine*& msgLine, int& offsetX ); /// Calculates value of the lineHeight attribute void CalcLineHeight(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |