diff --git a/Generals/Code/GameEngine/Include/Common/AsciiString.h b/Generals/Code/GameEngine/Include/Common/AsciiString.h index bc0ed31b03..27e474133b 100644 --- a/Generals/Code/GameEngine/Include/Common/AsciiString.h +++ b/Generals/Code/GameEngine/Include/Common/AsciiString.h @@ -228,6 +228,16 @@ class AsciiString */ void trim( void ); + /** + Remove trailing whitespace from the string. + */ + void trimEnd(void); + + /** + Remove all consecutive occurances of c from the end of the string. + */ + void trimEnd(const char c); + /** Make the string lowercase */ @@ -240,6 +250,18 @@ class AsciiString */ void removeLastChar(); + /** + Remove the final charCount characters in the string. If the string is empty, + do nothing. + */ + void truncateBy(const Int charCount); + + /** + Truncate the string to a length of maxLength characters, not including null termination, + by removing from the end. If the string is empty or shorter than maxLength, do nothing. + */ + void truncateTo(const Int maxLength); + /** Analogous to sprintf() -- this formats a string according to the given sprintf-style format string (and the variable argument list) diff --git a/Generals/Code/GameEngine/Include/Common/UnicodeString.h b/Generals/Code/GameEngine/Include/Common/UnicodeString.h index e455f71ba6..eb27882b55 100644 --- a/Generals/Code/GameEngine/Include/Common/UnicodeString.h +++ b/Generals/Code/GameEngine/Include/Common/UnicodeString.h @@ -228,6 +228,16 @@ class UnicodeString */ void trim( void ); + /** + Remove trailing whitespace from the string. + */ + void trimEnd(void); + + /** + Remove all consecutive occurances of c from the end of the string. + */ + void trimEnd(const WideChar c); + /** Remove the final character in the string. If the string is empty, do nothing. (This is a rather dorky method, but used a lot in @@ -235,6 +245,18 @@ class UnicodeString */ void removeLastChar(); + /** + Remove the final charCount characters in the string. If the string is empty, + do nothing. + */ + void truncateBy(const Int charCount); + + /** + Truncate the string to a length of maxLength characters, not including null termination, + by removing from the end. If the string is empty or shorter than maxLength, do nothing. + */ + void truncateTo(const Int maxLength); + /** Analogous to sprintf() -- this formats a string according to the given sprintf-style format string (and the variable argument list) diff --git a/Generals/Code/GameEngine/Include/GameClient/DisplayString.h b/Generals/Code/GameEngine/Include/GameClient/DisplayString.h index 642157e058..fe30c09316 100644 --- a/Generals/Code/GameEngine/Include/GameClient/DisplayString.h +++ b/Generals/Code/GameEngine/Include/GameClient/DisplayString.h @@ -100,6 +100,9 @@ class DisplayString : public MemoryPoolObject virtual void setClipRegion( IRegion2D *region ); ///< clip text in this region virtual void removeLastChar( void ); ///< remove the last character + virtual void truncateBy(const Int charCount); ///< remove the last charCount characters + virtual void truncateTo(const Int maxLength); ///< remove characters, if needed, until the string is maxLength long excluding null terminator + virtual void appendChar( WideChar c ); ///< append character to end DisplayString *next( void ); ///< return next string diff --git a/Generals/Code/GameEngine/Source/Common/CommandLine.cpp b/Generals/Code/GameEngine/Source/Common/CommandLine.cpp index 186bf0297e..7e6eea47cf 100644 --- a/Generals/Code/GameEngine/Source/Common/CommandLine.cpp +++ b/Generals/Code/GameEngine/Source/Common/CommandLine.cpp @@ -95,10 +95,7 @@ static void ConvertShortMapPathToLongMapPath(AsciiString &mapName) DEBUG_CRASH(("Invalid map name %s", mapName.str())); } // remove the .map from the end. - token.removeLastChar(); - token.removeLastChar(); - token.removeLastChar(); - token.removeLastChar(); + token.truncateBy(4); actualpath.concat(token); actualpath.concat('\\'); diff --git a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp index 7b05298be1..89f3e3786a 100644 --- a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp @@ -897,9 +897,7 @@ void updateTGAtoDDS() } // replace tga with dds - filenameDDS.removeLastChar(); // a - filenameDDS.removeLastChar(); // g - filenameDDS.removeLastChar(); // t + filenameDDS.truncateBy(3); // "tga" filenameDDS.concat("dds"); Bool needsToBeUpdated = FALSE; diff --git a/Generals/Code/GameEngine/Source/Common/Recorder.cpp b/Generals/Code/GameEngine/Source/Common/Recorder.cpp index 2cf23da987..d125045d56 100644 --- a/Generals/Code/GameEngine/Source/Common/Recorder.cpp +++ b/Generals/Code/GameEngine/Source/Common/Recorder.cpp @@ -297,9 +297,7 @@ void RecorderClass::cleanUpReplayFile( void ) return; AsciiString debugFname = fname; - debugFname.removeLastChar(); - debugFname.removeLastChar(); - debugFname.removeLastChar(); + debugFname.truncateBy(3); debugFname.concat("txt"); UnsignedInt fileSize = 0; FILE *fp = fopen(logFileName, "rb"); diff --git a/Generals/Code/GameEngine/Source/Common/StatsCollector.cpp b/Generals/Code/GameEngine/Source/Common/StatsCollector.cpp index 26ffa4ef19..6df9fe6774 100644 --- a/Generals/Code/GameEngine/Source/Common/StatsCollector.cpp +++ b/Generals/Code/GameEngine/Source/Common/StatsCollector.cpp @@ -317,10 +317,7 @@ void StatsCollector::createFileName( void ) const char *fname = name.reverseFind('\\'); if (fname) name = fname+1; - name.removeLastChar(); // p - name.removeLastChar(); // a - name.removeLastChar(); // m - name.removeLastChar(); // . + name.truncateBy(4); // ".map" m_statsFileName.clear(); #if defined(RTS_DEBUG) if (TheGlobalData->m_saveStats) diff --git a/Generals/Code/GameEngine/Source/Common/System/AsciiString.cpp b/Generals/Code/GameEngine/Source/Common/System/AsciiString.cpp index a05b52a3b7..1888333399 100644 --- a/Generals/Code/GameEngine/Source/Common/System/AsciiString.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/AsciiString.cpp @@ -289,21 +289,52 @@ void AsciiString::trim() set(c); } - if (m_data) // another check, because the previous set() could erase m_data + trimEnd(); + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::trimEnd() +{ + validate(); + + if (m_data) + { + // Clip trailing white space from the string. + const int len = strlen(peek()); + int index = len; + while (index > 0 && isspace(getCharAt(index - 1))) { - // Clip trailing white space from the string. - int len = strlen(peek()); - for (int index = len-1; index >= 0; index--) - { - if (isspace(getCharAt(index))) - { - removeLastChar(); - } - else - { - break; - } - } + --index; + } + + if (index < len) + { + truncateTo(index); + } + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::trimEnd(const char c) +{ + validate(); + + if (m_data) + { + // Clip trailing consecutive occurances of c from the string. + const int len = strlen(peek()); + int index = len; + while (index > 0 && getCharAt(index - 1) == c) + { + --index; + } + + if (index < len) + { + truncateTo(index); } } validate(); @@ -331,15 +362,42 @@ void AsciiString::toLower() // ----------------------------------------------------- void AsciiString::removeLastChar() +{ + truncateBy(1); +} + +// ----------------------------------------------------- +void AsciiString::truncateBy(const Int charCount) { validate(); - if (m_data) + if (m_data && charCount > 0) { - int len = strlen(peek()); + const size_t len = strlen(peek()); if (len > 0) { - ensureUniqueBufferOfSize(len+1, true, NULL, NULL); - peek()[len - 1] = 0; + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + size_t count = charCount; + if (charCount > len) + { + count = len; + } + peek()[len - count] = 0; + } + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::truncateTo(const Int maxLength) +{ + validate(); + if (m_data) + { + const size_t len = strlen(peek()); + if (len > maxLength) + { + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + peek()[maxLength] = 0; } } validate(); diff --git a/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp b/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp index 9e774cb028..3f6d0b527f 100644 --- a/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp @@ -408,9 +408,8 @@ static void findHighFileNumber( AsciiString filename, void *userData ) // strip off the extension at the end of the filename AsciiString nameOnly = filename; - for( size_t count = 0; count < strlen( SAVE_GAME_EXTENSION ); count++ ) - nameOnly.removeLastChar(); - + nameOnly.truncateBy( strlen( SAVE_GAME_EXTENSION ) ); + // convert filename (which is only numbers) to a number Int fileNumber = atoi( nameOnly.str() ); diff --git a/Generals/Code/GameEngine/Source/Common/System/UnicodeString.cpp b/Generals/Code/GameEngine/Source/Common/System/UnicodeString.cpp index bae146c650..93038ecee9 100644 --- a/Generals/Code/GameEngine/Source/Common/System/UnicodeString.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/UnicodeString.cpp @@ -241,37 +241,95 @@ void UnicodeString::trim() set(c); } - if (m_data) // another check, because the previous set() could erase m_data + trimEnd(); + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::trimEnd() +{ + validate(); + + if (m_data) + { + // Clip trailing white space from the string. + const int len = wcslen(peek()); + int index = len; + while (index > 0 && iswspace(getCharAt(index - 1))) + { + --index; + } + + if (index < len) + { + truncateTo(index); + } + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::trimEnd(const WideChar c) +{ + validate(); + + if (m_data) + { + // Clip trailing consecutive occurances of c from the string. + const int len = wcslen(peek()); + int index = len; + while (index > 0 && getCharAt(index - 1) == c) + { + --index; + } + + if (index < len) { - // Clip trailing white space from the string. - int len = wcslen(peek()); - for (int index = len-1; index >= 0; index--) + truncateTo(index); + } + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::removeLastChar() +{ + truncateBy(1); +} + +// ----------------------------------------------------- +void UnicodeString::truncateBy(const Int charCount) +{ + validate(); + if (m_data && charCount > 0) + { + const size_t len = wcslen(peek()); + if (len > 0) + { + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + size_t count = charCount; + if (charCount > len) { - if (iswspace(getCharAt(index))) - { - removeLastChar(); - } - else - { - break; - } + count = len; } + peek()[len - count] = 0; } } validate(); } // ----------------------------------------------------- -void UnicodeString::removeLastChar() +void UnicodeString::truncateTo(const Int maxLength) { validate(); if (m_data) { - int len = wcslen(peek()); - if (len > 0) + const size_t len = wcslen(peek()); + if (len > maxLength) { - ensureUniqueBufferOfSize(len+1, true, NULL, NULL); - peek()[len - 1] = 0; + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + peek()[maxLength] = 0; } } validate(); diff --git a/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp b/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp index b17c883fc9..e3ed145f33 100644 --- a/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp +++ b/Generals/Code/GameEngine/Source/Common/UserPreferences.cpp @@ -802,11 +802,7 @@ Bool LadderPreferences::loadProfile( Int profileID ) continue; p.port = atoi( ptr + 1 ); - Int i=0; - for (; i g_lanPlayerNameLength) - defaultName.removeLastChar(); + defaultName.truncateTo(g_lanPlayerNameLength); + GadgetTextEntrySetText( textEntryPlayerName, defaultName); // Clear the text entry line GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); @@ -431,8 +431,7 @@ void LanLobbyMenuInit( WindowLayout *layout, void *userData ) GadgetListBoxReset(listboxPlayers); GadgetListBoxReset(listboxGames); - while (defaultName.getLength() > g_lanPlayerNameLength) - defaultName.removeLastChar(); + defaultName.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(defaultName); TheLAN->RequestLocations(); @@ -815,8 +814,7 @@ WindowMsgHandledType LanLobbyMenuSystem( GameWindow *window, UnsignedInt msg, else txtInput = UnicodeString::TheEmptyString; - while (txtInput.getLength() > g_lanPlayerNameLength) - txtInput.removeLastChar(); + txtInput.truncateTo(g_lanPlayerNameLength); if (!txtInput.isEmpty() && txtInput.getCharAt(txtInput.getLength()-1) == L',') txtInput.removeLastChar(); // we use , for strtok's so we can't allow them in names. :( diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp index 1f449d7068..171d6431c3 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp @@ -197,8 +197,7 @@ void HostDirectConnectGame() prefs["UserName"] = UnicodeStringToQuotedPrintable(name); prefs.write(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); TheLAN->RequestGameCreate(localIPString, TRUE); } @@ -241,8 +240,7 @@ void JoinDirectConnectGame() UpdateRemoteIPList(); PopulateRemoteIPComboBox(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); TheLAN->RequestGameJoinDirectConnect(ipaddress); @@ -500,8 +498,7 @@ WindowMsgHandledType NetworkDirectConnectSystem( GameWindow *window, UnsignedInt prefs["UserName"] = UnicodeStringToQuotedPrintable(name); prefs.write(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); buttonPushed = true; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp index c3ddc3041e..efda7e5c8a 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp @@ -124,8 +124,7 @@ static Bool readReplayMapInfo(const AsciiString& filename, RecorderClass::Replay static void removeReplayExtension(UnicodeString& replayName) { const Int extensionLength = TheRecorder->getReplayExtention().getLength(); - for (Int k=0; k < extensionLength; ++k) - replayName.removeLastChar(); + replayName.truncateBy(extensionLength); } //------------------------------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp index bd553e735e..353f60e284 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp @@ -550,10 +550,7 @@ void HandleBuddyResponses( void ) } // end if UnicodeString snippet = message.m_message; - while (snippet.getLength() > 11) - { - snippet.removeLastChar(); - } + snippet.truncateTo(11); UnicodeString s; s.format(TheGameText->fetch("Buddy:MessageNotification"), nick.str(), snippet.str()); lastNotificationWasStatus = FALSE; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp index b2555349d9..80777de607 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp @@ -1066,17 +1066,13 @@ WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, trimmedEmail.trim(); if (!trimmedNick.isEmpty()) { - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'\\') - trimmedNick.removeLastChar(); - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'/') - trimmedNick.removeLastChar(); + trimmedNick.trimEnd(L'\\'); + trimmedNick.trimEnd(L'/'); } if (!trimmedEmail.isEmpty()) { - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'\\') - trimmedEmail.removeLastChar(); - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'/') - trimmedEmail.removeLastChar(); + trimmedEmail.trimEnd(L'\\'); + trimmedEmail.trimEnd(L'/'); } if (trimmedEmail.getLength() != uEmail.getLength()) { @@ -1466,19 +1462,7 @@ WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, { UnicodeString uniLine; uniLine = UnicodeString(MultiByteToWideCharSingleLine(asciiLine.str()).c_str()); - int len = uniLine.getLength(); - for (int index = len-1; index >= 0; index--) - { - if (iswspace(uniLine.getCharAt(index))) - { - uniLine.removeLastChar(); - } - else - { - break; - } - } - //uniLine.trim(); + uniLine.trimEnd(); DEBUG_LOG(("adding TOS line: [%ls]", uniLine.str())); GadgetListBoxAddEntryText(listboxTOS, uniLine, tosColor, -1); } diff --git a/Generals/Code/GameEngine/Source/GameClient/MapUtil.cpp b/Generals/Code/GameEngine/Source/GameClient/MapUtil.cpp index e104fd474a..6228761105 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MapUtil.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MapUtil.cpp @@ -572,8 +572,7 @@ Bool MapCache::loadUserMaps() { AsciiString endingStr; AsciiString fname = s+1; - for (size_t i=0; iinitMapStringFile(stringFileName); md.m_displayName = TheGameText->fetch(munkee); @@ -1066,10 +1064,7 @@ Image *getMapPreviewImage( AsciiString mapName ) AsciiString name; AsciiString tempName; AsciiString filename; - tgaName.removeLastChar(); // p - tgaName.removeLastChar(); // a - tgaName.removeLastChar(); // m - tgaName.removeLastChar(); // . + tgaName.truncateBy(4); // ".map" name = tgaName;//.reverseFind('\\') + 1; filename = tgaName.reverseFind('\\') + 1; //tgaName = name; diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index 26fb2275d6..a9e52baa3e 100644 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -512,9 +512,7 @@ void GameInfo::setMap( AsciiString mapName ) { m_mapMask = 1; AsciiString path = mapName; - path.removeLastChar(); - path.removeLastChar(); - path.removeLastChar(); + path.truncateBy(3); path.concat("tga"); DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str())); File *fp = TheFileSystem->openFile(path.str()); diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp index 81260cd63f..ef1e43f543 100644 --- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp +++ b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp @@ -87,8 +87,7 @@ static LadderInfo *parseLadder(AsciiString raw) line.nextToken(&tokenHomepage, " "); lad->name = MultiByteToWideCharSingleLine(tokenName.str()).c_str(); - while (lad->name.getLength() > 20) - lad->name.removeLastChar(); // Per Harvard's request, ladder names are limited to 20 chars + lad->name.truncateTo(20); // Per Harvard's request, ladder names are limited to 20 chars lad->address = tokenAddr; lad->port = atoi(tokenPort.str()); lad->homepageURL = tokenHomepage; diff --git a/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp index 5abf73c50d..ee364ea238 100644 --- a/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp +++ b/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp @@ -894,8 +894,7 @@ void LANAPI::RequestGameCreate( UnicodeString gameName, Bool isDirectConnect ) else s.concat(gameName); - while (s.getLength() > g_lanGameNameLength) - s.removeLastChar(); + s.truncateTo(g_lanGameNameLength); DEBUG_LOG(("Setting local game name to '%ls'", s.str())); diff --git a/Generals/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp b/Generals/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp index 26216aa18d..b67970a143 100644 --- a/Generals/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp @@ -1348,8 +1348,11 @@ BOOL CWorldBuilderDoc::OnOpenDocument(LPCTSTR lpszPathName) // clear out map-specific text TheGameText->reset(); AsciiString s = lpszPathName; - while (s.getLength() && s.getCharAt(s.getLength()-1) != '\\') - s.removeLastChar(); + const char* lastSep = s.reverseFind('\\'); + if (lastSep != NULL) + { + s.truncateTo(lastSep - s.str() + 1); + } s.concat("map.str"); DEBUG_LOG(("Looking for map-specific text in [%s]", s.str())); TheGameText->initMapStringFile(s); diff --git a/GeneralsMD/Code/GameEngine/Include/Common/AsciiString.h b/GeneralsMD/Code/GameEngine/Include/Common/AsciiString.h index 1abeabb7b3..213f048182 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/AsciiString.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/AsciiString.h @@ -228,6 +228,16 @@ class AsciiString */ void trim( void ); + /** + Remove trailing whitespace from the string. + */ + void trimEnd(void); + + /** + Remove all consecutive occurances of c from the end of the string. + */ + void trimEnd(const char c); + /** Make the string lowercase */ @@ -240,6 +250,18 @@ class AsciiString */ void removeLastChar(); + /** + Remove the final charCount characters in the string. If the string is empty, + do nothing. + */ + void truncateBy(const Int charCount); + + /** + Truncate the string to a length of maxLength characters, not including null termination, + by removing from the end. If the string is empty or shorter than maxLength, do nothing. + */ + void truncateTo(const Int maxLength); + /** Analogous to sprintf() -- this formats a string according to the given sprintf-style format string (and the variable argument list) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/UnicodeString.h b/GeneralsMD/Code/GameEngine/Include/Common/UnicodeString.h index 7038d31e98..b138ab6929 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/UnicodeString.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/UnicodeString.h @@ -228,6 +228,16 @@ class UnicodeString */ void trim( void ); + /** + Remove trailing whitespace from the string. + */ + void trimEnd(void); + + /** + Remove all consecutive occurances of c from the end of the string. + */ + void trimEnd(const WideChar c); + /** Remove the final character in the string. If the string is empty, do nothing. (This is a rather dorky method, but used a lot in @@ -235,6 +245,18 @@ class UnicodeString */ void removeLastChar(); + /** + Remove the final charCount characters in the string. If the string is empty, + do nothing. + */ + void truncateBy(const Int charCount); + + /** + Truncate the string to a length of maxLength characters, not including null termination, + by removing from the end. If the string is empty or shorter than maxLength, do nothing. + */ + void truncateTo(const Int maxLength); + /** Analogous to sprintf() -- this formats a string according to the given sprintf-style format string (and the variable argument list) diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h b/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h index e0ca7336c1..97e0c0c17f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h @@ -100,6 +100,9 @@ class DisplayString : public MemoryPoolObject virtual void setClipRegion( IRegion2D *region ); ///< clip text in this region virtual void removeLastChar( void ); ///< remove the last character + virtual void truncateBy(const Int charCount); ///< remove the last charCount characters + virtual void truncateTo(const Int maxLength); ///< remove characters, if needed, until the string is maxLength long excluding null terminator + virtual void appendChar( WideChar c ); ///< append character to end DisplayString *next( void ); ///< return next string diff --git a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp index d9c0ab9421..fb64d4b88f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp @@ -95,10 +95,7 @@ static void ConvertShortMapPathToLongMapPath(AsciiString &mapName) DEBUG_CRASH(("Invalid map name %s", mapName.str())); } // remove the .map from the end. - token.removeLastChar(); - token.removeLastChar(); - token.removeLastChar(); - token.removeLastChar(); + token.truncateBy(4); actualpath.concat(token); actualpath.concat('\\'); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp index f90fd651c5..8ae4d22272 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp @@ -957,9 +957,7 @@ void updateTGAtoDDS() } // replace tga with dds - filenameDDS.removeLastChar(); // a - filenameDDS.removeLastChar(); // g - filenameDDS.removeLastChar(); // t + filenameDDS.truncateBy(3); // tga filenameDDS.concat("dds"); Bool needsToBeUpdated = FALSE; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp index bd771dd06a..8f7d895c0f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp @@ -297,9 +297,7 @@ void RecorderClass::cleanUpReplayFile( void ) return; AsciiString debugFname = fname; - debugFname.removeLastChar(); - debugFname.removeLastChar(); - debugFname.removeLastChar(); + debugFname.truncateBy(3); debugFname.concat("txt"); UnsignedInt fileSize = 0; FILE *fp = fopen(logFileName, "rb"); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/StatsCollector.cpp b/GeneralsMD/Code/GameEngine/Source/Common/StatsCollector.cpp index 0d6e080350..a5099f5bb6 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/StatsCollector.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/StatsCollector.cpp @@ -317,10 +317,7 @@ void StatsCollector::createFileName( void ) const char *fname = name.reverseFind('\\'); if (fname) name = fname+1; - name.removeLastChar(); // p - name.removeLastChar(); // a - name.removeLastChar(); // m - name.removeLastChar(); // . + name.truncateBy(4); // ".map" m_statsFileName.clear(); #if defined(RTS_DEBUG) if (TheGlobalData->m_saveStats) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/AsciiString.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/AsciiString.cpp index 7a935ddaad..79a45e30a7 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/AsciiString.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/AsciiString.cpp @@ -289,21 +289,52 @@ void AsciiString::trim() set(c); } - if (m_data) // another check, because the previous set() could erase m_data + trimEnd(); + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::trimEnd() +{ + validate(); + + if (m_data) + { + // Clip trailing white space from the string. + const int len = strlen(peek()); + int index = len; + while (index > 0 && isspace(getCharAt(index - 1))) { - // Clip trailing white space from the string. - int len = strlen(peek()); - for (int index = len-1; index >= 0; index--) - { - if (isspace(getCharAt(index))) - { - removeLastChar(); - } - else - { - break; - } - } + --index; + } + + if (index < len) + { + truncateTo(index); + } + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::trimEnd(const char c) +{ + validate(); + + if (m_data) + { + // Clip trailing consecutive occurances of c from the string. + const int len = strlen(peek()); + int index = len; + while (index > 0 && getCharAt(index - 1) == c) + { + --index; + } + + if (index < len) + { + truncateTo(index); } } validate(); @@ -331,15 +362,42 @@ void AsciiString::toLower() // ----------------------------------------------------- void AsciiString::removeLastChar() +{ + truncateBy(1); +} + +// ----------------------------------------------------- +void AsciiString::truncateBy(const Int charCount) { validate(); - if (m_data) + if (m_data && charCount > 0) { - int len = strlen(peek()); + const size_t len = strlen(peek()); if (len > 0) { ensureUniqueBufferOfSize(len+1, true, NULL, NULL); - peek()[len - 1] = 0; + size_t count = charCount; + if (charCount > len) + { + count = len; + } + peek()[len - count] = 0; + } + } + validate(); +} + +// ----------------------------------------------------- +void AsciiString::truncateTo(const Int maxLength) +{ + validate(); + if (m_data) + { + const size_t len = strlen(peek()); + if (len > maxLength) + { + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + peek()[maxLength] = 0; } } validate(); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp index 171bcd74ba..f95bed1777 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp @@ -408,8 +408,7 @@ static void findHighFileNumber( AsciiString filename, void *userData ) // strip off the extension at the end of the filename AsciiString nameOnly = filename; - for( size_t count = 0; count < strlen( SAVE_GAME_EXTENSION ); count++ ) - nameOnly.removeLastChar(); + nameOnly.truncateBy( strlen( SAVE_GAME_EXTENSION ) ); // convert filename (which is only numbers) to a number Int fileNumber = atoi( nameOnly.str() ); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/UnicodeString.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/UnicodeString.cpp index 2ca7f51f07..8eae0040d9 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/UnicodeString.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/UnicodeString.cpp @@ -241,37 +241,95 @@ void UnicodeString::trim() set(c); } - if (m_data) // another check, because the previous set() could erase m_data + trimEnd(); + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::trimEnd() +{ + validate(); + + if (m_data) + { + // Clip trailing white space from the string. + const int len = wcslen(peek()); + int index = len; + while (index > 0 && iswspace(getCharAt(index - 1))) { - // Clip trailing white space from the string. - int len = wcslen(peek()); - for (int index = len-1; index >= 0; index--) - { - if (iswspace(getCharAt(index))) - { - removeLastChar(); - } - else - { - break; - } - } + --index; + } + + if (index < len) + { + truncateTo(index); } } validate(); } // ----------------------------------------------------- -void UnicodeString::removeLastChar() +void UnicodeString::trimEnd(const WideChar c) { validate(); + if (m_data) { - int len = wcslen(peek()); + // Clip trailing consecutive occurances of c from the string. + const int len = wcslen(peek()); + int index = len; + while (index > 0 && getCharAt(index - 1) == c) + { + --index; + } + + if (index < len) + { + truncateTo(index); + } + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::removeLastChar() +{ + truncateBy(1); +} + +// ----------------------------------------------------- +void UnicodeString::truncateBy(const Int charCount) +{ + validate(); + if (m_data && charCount > 0) + { + const size_t len = wcslen(peek()); if (len > 0) { ensureUniqueBufferOfSize(len+1, true, NULL, NULL); - peek()[len - 1] = 0; + size_t count = charCount; + if (charCount > len) + { + count = len; + } + peek()[len - count] = 0; + } + } + validate(); +} + +// ----------------------------------------------------- +void UnicodeString::truncateTo(const Int maxLength) +{ + validate(); + if (m_data) + { + const size_t len = wcslen(peek()); + if (len > maxLength) + { + ensureUniqueBufferOfSize(len + 1, true, NULL, NULL); + peek()[maxLength] = 0; } } validate(); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/UserPreferences.cpp b/GeneralsMD/Code/GameEngine/Source/Common/UserPreferences.cpp index 83e80292fe..086f52887f 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/UserPreferences.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/UserPreferences.cpp @@ -899,11 +899,7 @@ Bool LadderPreferences::loadProfile( Int profileID ) continue; p.port = atoi( ptr + 1 ); - Int i=0; - for (; i g_lanPlayerNameLength) - defaultName.removeLastChar(); + defaultName.truncateTo(g_lanPlayerNameLength); + GadgetTextEntrySetText( textEntryPlayerName, defaultName); // Clear the text entry line GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString); @@ -473,8 +473,7 @@ void LanLobbyMenuInit( WindowLayout *layout, void *userData ) GadgetListBoxReset(listboxPlayers); GadgetListBoxReset(listboxGames); - while (defaultName.getLength() > g_lanPlayerNameLength) - defaultName.removeLastChar(); + defaultName.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(defaultName); TheLAN->RequestLocations(); @@ -857,8 +856,7 @@ WindowMsgHandledType LanLobbyMenuSystem( GameWindow *window, UnsignedInt msg, else txtInput = UnicodeString::TheEmptyString; - while (txtInput.getLength() > g_lanPlayerNameLength) - txtInput.removeLastChar(); + txtInput.truncateTo(g_lanPlayerNameLength); if (!txtInput.isEmpty() && txtInput.getCharAt(txtInput.getLength()-1) == L',') txtInput.removeLastChar(); // we use , for strtok's so we can't allow them in names. :( diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp index 7d1d7ca819..1dce39d403 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp @@ -197,8 +197,7 @@ void HostDirectConnectGame() prefs["UserName"] = UnicodeStringToQuotedPrintable(name); prefs.write(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); TheLAN->RequestGameCreate(localIPString, TRUE); } @@ -241,8 +240,7 @@ void JoinDirectConnectGame() UpdateRemoteIPList(); PopulateRemoteIPComboBox(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); TheLAN->RequestGameJoinDirectConnect(ipaddress); @@ -500,8 +498,7 @@ WindowMsgHandledType NetworkDirectConnectSystem( GameWindow *window, UnsignedInt prefs["UserName"] = UnicodeStringToQuotedPrintable(name); prefs.write(); - while (name.getLength() > g_lanPlayerNameLength) - name.removeLastChar(); + name.truncateTo(g_lanPlayerNameLength); TheLAN->RequestSetName(name); buttonPushed = true; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupSaveLoad.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupSaveLoad.cpp index a9fe3dc3cd..51a3905c33 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupSaveLoad.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupSaveLoad.cpp @@ -469,10 +469,7 @@ static void setEditDescription( GameWindow *editControl ) //Keep the extension out of the descriptive name. if( (defaultDesc.getLength() >= 4) && (defaultDesc.getCharAt(defaultDesc.getLength()-4) == '.') ) { - for( Int stripIndex = 0; stripIndex < 4; stripIndex++ ) - { - defaultDesc.removeLastChar(); - } + defaultDesc.truncateBy(4); } } // end else diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp index 6e5a5d0396..6b29e95cfd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ReplayMenu.cpp @@ -124,8 +124,7 @@ static Bool readReplayMapInfo(const AsciiString& filename, RecorderClass::Replay static void removeReplayExtension(UnicodeString& replayName) { const Int extensionLength = TheRecorder->getReplayExtention().getLength(); - for (Int k=0; k < extensionLength; ++k) - replayName.removeLastChar(); + replayName.truncateBy(extensionLength); } //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp index 096690365b..2eaf1d277c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp @@ -550,10 +550,8 @@ void HandleBuddyResponses( void ) } // end if UnicodeString snippet = message.m_message; - while (snippet.getLength() > 11) - { - snippet.removeLastChar(); - } + snippet.truncateTo(11); + UnicodeString s; s.format(TheGameText->fetch("Buddy:MessageNotification"), nick.str(), snippet.str()); lastNotificationWasStatus = FALSE; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp index 62283d0887..e6dfe3b2f1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp @@ -1066,17 +1066,13 @@ WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, trimmedEmail.trim(); if (!trimmedNick.isEmpty()) { - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'\\') - trimmedNick.removeLastChar(); - if (trimmedNick.getCharAt(trimmedNick.getLength()-1) == L'/') - trimmedNick.removeLastChar(); + trimmedNick.trimEnd(L'\\'); + trimmedNick.trimEnd(L'/'); } if (!trimmedEmail.isEmpty()) { - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'\\') - trimmedEmail.removeLastChar(); - if (trimmedEmail.getCharAt(trimmedEmail.getLength()-1) == L'/') - trimmedEmail.removeLastChar(); + trimmedEmail.trimEnd(L'\\'); + trimmedEmail.trimEnd(L'/'); } if (trimmedEmail.getLength() != uEmail.getLength()) { @@ -1466,19 +1462,7 @@ WindowMsgHandledType WOLLoginMenuSystem( GameWindow *window, UnsignedInt msg, { UnicodeString uniLine; uniLine = UnicodeString(MultiByteToWideCharSingleLine(asciiLine.str()).c_str()); - int len = uniLine.getLength(); - for (int index = len-1; index >= 0; index--) - { - if (iswspace(uniLine.getCharAt(index))) - { - uniLine.removeLastChar(); - } - else - { - break; - } - } - //uniLine.trim(); + uniLine.trimEnd(); DEBUG_LOG(("adding TOS line: [%ls]", uniLine.str())); GadgetListBoxAddEntryText(listboxTOS, uniLine, tosColor, -1); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MapUtil.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MapUtil.cpp index e520622297..afd61b6452 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MapUtil.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MapUtil.cpp @@ -574,8 +574,7 @@ Bool MapCache::loadUserMaps() { AsciiString endingStr; AsciiString fname = s+1; - for (size_t i=0; iinitMapStringFile(stringFileName); md.m_displayName = TheGameText->fetch(munkee); @@ -1146,10 +1144,7 @@ Image *getMapPreviewImage( AsciiString mapName ) AsciiString name; AsciiString tempName; AsciiString filename; - tgaName.removeLastChar(); // p - tgaName.removeLastChar(); // a - tgaName.removeLastChar(); // m - tgaName.removeLastChar(); // . + tgaName.truncateBy(4); // ".map" name = tgaName;//.reverseFind('\\') + 1; filename = tgaName.reverseFind('\\') + 1; //tgaName = name; diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp index 4a34ba21fa..273bdbc5dc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp @@ -517,9 +517,7 @@ void GameInfo::setMap( AsciiString mapName ) { m_mapMask = 1; AsciiString path = mapName; - path.removeLastChar(); - path.removeLastChar(); - path.removeLastChar(); + path.truncateBy(3); path.concat("tga"); DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str())); File *fp = TheFileSystem->openFile(path.str()); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp index f2bfbbfeca..6ec2e3b5bf 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp @@ -87,8 +87,7 @@ static LadderInfo *parseLadder(AsciiString raw) line.nextToken(&tokenHomepage, " "); lad->name = MultiByteToWideCharSingleLine(tokenName.str()).c_str(); - while (lad->name.getLength() > 20) - lad->name.removeLastChar(); // Per Harvard's request, ladder names are limited to 20 chars + lad->name.truncateTo(20); // Per Harvard's request, ladder names are limited to 20 chars lad->address = tokenAddr; lad->port = atoi(tokenPort.str()); lad->homepageURL = tokenHomepage; diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp index 06ca0d3749..797930d68d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp @@ -894,8 +894,7 @@ void LANAPI::RequestGameCreate( UnicodeString gameName, Bool isDirectConnect ) else s.concat(gameName); - while (s.getLength() > g_lanGameNameLength) - s.removeLastChar(); + s.truncateTo(g_lanGameNameLength); DEBUG_LOG(("Setting local game name to '%ls'", s.str())); diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp index 8c63a7bbd7..93fc9f00a7 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilderDoc.cpp @@ -1405,8 +1405,11 @@ BOOL CWorldBuilderDoc::OnOpenDocument(LPCTSTR lpszPathName) // clear out map-specific text TheGameText->reset(); AsciiString s = lpszPathName; - while (s.getLength() && s.getCharAt(s.getLength()-1) != '\\') - s.removeLastChar(); + const char* lastSep = s.reverseFind('\\'); + if (lastSep != NULL) + { + s.truncateTo(lastSep - s.str() + 1); + } s.concat("map.str"); DEBUG_LOG(("Looking for map-specific text in [%s]", s.str())); TheGameText->initMapStringFile(s);