Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ if (IS_VS6_BUILD)
add_subdirectory(Dependencies/MaxSDK)
endif()
add_subdirectory(Dependencies/Utility)
if (WIN32)
add_subdirectory(Dependencies/Usp10)
else()
add_library(deps_usp10 INTERFACE)
endif()

# To be removed when abandoning VC6
if (IS_VS6_BUILD)
Expand Down
12 changes: 12 additions & 0 deletions Core/GameEngine/Include/GameClient/DisplayString.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class DisplayString : public MemoryPoolObject
virtual void draw( Int x, Int y, Color color, Color dropColor, Int xDrop, Int yDrop ) = 0; ///< render text with the drop shadow being at the offsets passed in
virtual void getSize( Int *width, Int *height ) = 0; ///< get render size
virtual Int getWidth( Int charPos = -1 ) = 0; ///< get text with up to charPos characters, 1- = all characters
virtual Int getCaretOffset() = 0; ///< get the horizontal offset of a caret after the last character
virtual Bool isRightToLeft() = 0; ///< TRUE if the text starts with a right-to-left paragraph

virtual void setUseHotkey( Bool useHotkey, Color hotKeyColor ) = 0;

Expand Down Expand Up @@ -126,3 +128,13 @@ inline void DisplayString::notifyTextChanged() {}
inline DisplayString *DisplayString::next() { return m_next; }

// EXTERNALS //////////////////////////////////////////////////////////////////

// TheSuperHackers @feature Wraps text, such as a player name or a chat message, in a Unicode
// first strong isolate if it contains right-to-left characters, so that it keeps its own reading
// order when it is shown next to other text, as in "[name] message".
UnicodeString IsolateBidiText( const UnicodeString &text );

// TheSuperHackers @feature Applies IsolateBidiText to the names in the leading brackets of a chat line
// that was put together elsewhere, such as "[name] message" or "[tag] [name] message", and to the
// message after them.
UnicodeString IsolateBidiChatLine( const UnicodeString &line );
52 changes: 52 additions & 0 deletions Core/GameEngine/Source/GameClient/DisplayString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,62 @@

// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////

// Hebrew, Arabic and the other right-to-left scripts of the Basic Multilingual Plane
static Bool isRightToLeftChar( WideChar ch )
{
return (ch >= 0x0590 && ch <= 0x08FF) || (ch >= 0xFB1D && ch <= 0xFDFF) || (ch >= 0xFE70 && ch <= 0xFEFC);
}

///////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// IsolateBidiText ============================================================
/** Text without right-to-left characters is returned as it is, so that it is
* still drawn by the glyph cache of the font. */
//=============================================================================
UnicodeString IsolateBidiText( const UnicodeString &text )
{
const WideChar *str = text.str();
for( Int i = 0; str[i] != 0; ++i )
{
if( isRightToLeftChar( str[i] ) )
{
UnicodeString isolated;
isolated.concat( (WideChar)0x2068 ); // first strong isolate
isolated.concat( text );
isolated.concat( (WideChar)0x2069 ); // pop directional isolate
return isolated;
}
}
return text;
}

// IsolateBidiChatLine ========================================================
/** A leading group ends at the first closing bracket that a space follows */
//=============================================================================
UnicodeString IsolateBidiChatLine( const UnicodeString &line )
{
UnicodeString result;
const WideChar *str = line.str();
while( str[0] == L'[' )
{
const WideChar *close = wcschr( str, L']' );
if( close == nullptr || close[1] != L' ' )
break;

UnicodeString name;
name.set( str + 1, (Int)(close - str - 1) );
result.concat( L'[' );
result.concat( IsolateBidiText( name ) );
result.concat( L"] " );
str = close + 2;
}

result.concat( IsolateBidiText( UnicodeString( str ) ) );
return result;
}

// DisplayString::DisplayString ===============================================
/** */
//=============================================================================
Expand Down
5 changes: 3 additions & 2 deletions Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "Common/Recorder.h"

#include "GameClient/Diplomacy.h"
#include "GameClient/DisplayString.h"
#include "GameClient/GameText.h"
#include "GameClient/MessageBox.h"
#include "GameNetwork/ConnectionManager.h"
Expand Down Expand Up @@ -752,7 +753,7 @@ void ConnectionManager::processDisconnectChat(NetDisconnectChatCommandMsg *msg)
} else if (isPlayerConnected(playerID)) {
name = m_connections[playerID]->getUser()->GetName();
}
unitext.format(L"[%ls] %ls", name.str(), msg->getText().str());
unitext.format(L"[%ls] %ls", IsolateBidiText(name).str(), IsolateBidiText(msg->getText()).str());
// DEBUG_LOG(("ConnectionManager::processDisconnectChat - got message from player %d, message is %ls", playerID, unitext.str()));
TheDisconnectMenu->showChat(unitext); // <-- need to implement this
}
Expand All @@ -773,7 +774,7 @@ void ConnectionManager::processChat(NetChatCommandMsg *msg)
name = m_connections[playerID]->getUser()->GetName();
//DEBUG_LOG(("connection is non-null, using %ls", name.str()));
}
unitext.format(L"[%ls] %ls", name.str(), msg->getText().str());
unitext.format(L"[%ls] %ls", IsolateBidiText(name).str(), IsolateBidiText(msg->getText()).str());
// DEBUG_LOG(("ConnectionManager::processChat - got message from player %d (mask %8.8X), message is %ls", playerID, msg->getPlayerMask(), unitext.str()));

AsciiString playerName;
Expand Down
5 changes: 3 additions & 2 deletions Core/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "Common/AudioEventRTS.h"
#include "Common/INI.h"
#include "GameClient/DisplayString.h"
#include "GameClient/GameText.h"
#include "GameClient/GadgetListBox.h"
#include "GameClient/LanguageFilter.h"
Expand Down Expand Up @@ -301,11 +302,11 @@ void GameSpyInfo::addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool
UnicodeString fullMsg;
if (isAction)
{
fullMsg.format( L"%ls %ls", name.str(), msg.str() );
fullMsg.format( L"%ls %ls", IsolateBidiText(name).str(), IsolateBidiText(msg).str() );
}
else
{
fullMsg.format( L"[%ls] %ls", name.str(), msg.str() );
fullMsg.format( L"[%ls] %ls", IsolateBidiText(name).str(), IsolateBidiText(msg).str() );
}

Int index = addText(fullMsg, GameSpyColor[style], win);
Expand Down
9 changes: 5 additions & 4 deletions Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "Common/QuotedPrintable.h"
#include "Common/RandomValue.h"
#include "Common/UserPreferences.h"
#include "GameClient/DisplayString.h"
#include "GameClient/GameText.h"
#include "GameClient/LanguageFilter.h"
#include "GameClient/MapUtil.h"
Expand Down Expand Up @@ -690,9 +691,9 @@ void LANAPI::OnChat( UnicodeString player, UnsignedInt ip, UnicodeString message
index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatSystemColor, -1, -1);
break;
case LANAPIInterface::LANCHAT_EMOTE:
unicodeChat = player;
unicodeChat = IsolateBidiText(player);
unicodeChat.concat(L' ');
unicodeChat.concat(message);
unicodeChat.concat(IsolateBidiText(message));
if (ip == m_localIP)
index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatLocalActionColor, -1, -1);
else
Expand Down Expand Up @@ -721,9 +722,9 @@ void LANAPI::OnChat( UnicodeString player, UnsignedInt ip, UnicodeString message
}

unicodeChat = L"[";
unicodeChat.concat(player);
unicodeChat.concat(IsolateBidiText(player));
unicodeChat.concat(L"] ");
unicodeChat.concat(message);
unicodeChat.concat(IsolateBidiText(message));
if (ip == m_localIP)
index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatColor, -1, -1);
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ static void drawTextEntryText( GameWindow *window, WinInstanceData *instData,
// get the size of our text, and construct text
Int textWidth = text->getWidth();

// TheSuperHackers @feature Right-to-left text ends on its left side, so the caret
// follows the last character instead of the right edge of the text.
Int caretOffset = text->getCaretOffset();
Bool rightToLeft = text->isRightToLeft();

if (!e->drawTextFromStart)
{
// clip the text to the edit window size
Expand All @@ -153,14 +158,17 @@ static void drawTextEntryText( GameWindow *window, WinInstanceData *instData,
// draw the text
if(textWidth < width)
{
text->draw( x, y, textColor, textDropColor );
cursorPos = textWidth + x;
// right-to-left text starts at the right edge of the entry
Int textX = rightToLeft ? x + width - 4 - textWidth : x;
text->draw( textX, y, textColor, textDropColor );
cursorPos = caretOffset + textX;
}
else
{
Int div = textWidth / (width / 2) - 1;
// scroll by half the entry width until the caret is visible
Int div = max( caretOffset / (width / 2) - 1, 0 );
text->draw(x - (div * (width/2)), y, textColor, textDropColor);
cursorPos = textWidth - (div * (width/2)) + x;
cursorPos = caretOffset - (div * (width/2)) + x;
}

//cursorPos = x + textWidth;
Expand All @@ -183,9 +191,13 @@ static void drawTextEntryText( GameWindow *window, WinInstanceData *instData,
x+= 5;
// draw the text
text->draw( x, y, textColor, textDropColor );
cursorPos = textWidth + x;
cursorPos = caretOffset + x;
}

// the next right-to-left character goes left of the caret, so draw the caret left of its position
if (rightToLeft)
cursorPos -= 2;

if (e->constructText->getTextLength() > 0 )
{
e->constructText->draw( x + textWidth, y, compositeColor, compositeDropColor );
Expand Down
1 change: 1 addition & 0 deletions Core/Libraries/Source/WWVegas/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ target_compile_definitions(core_wwcommon INTERFACE

target_link_libraries(core_wwcommon INTERFACE
d3d8lib
deps_usp10
milesstub
stlport
)
Expand Down
7 changes: 7 additions & 0 deletions Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,13 @@ set(WW3D2_SRC
ww3dtrig.h
)

if (WIN32)
list(APPEND WW3D2_SRC
shapedtext.cpp
shapedtext.h
)
endif()

add_library(corei_ww3d2 INTERFACE)

target_sources(corei_ww3d2 INTERFACE ${WW3D2_SRC})
Expand Down
Loading