1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-20 12:36:05 +08:00

Imported more changes from sdk2013.

This commit is contained in:
Scott Ehlert
2017-05-30 15:22:52 -05:00
parent d73aca3068
commit 7ee1f97dd6
20 changed files with 776 additions and 473 deletions

View File

@ -992,9 +992,240 @@ char *V_pretifynum( int64 value )
return out;
}
//-----------------------------------------------------------------------------
// Purpose: returns true if a wide character is a "mean" space; that is,
// if it is technically a space or punctuation, but causes disruptive
// behavior when used in names, web pages, chat windows, etc.
//
// characters in this set are removed from the beginning and/or end of strings
// by Q_AggressiveStripPrecedingAndTrailingWhitespaceW()
//-----------------------------------------------------------------------------
bool Q_IsMeanSpaceW( wchar_t wch )
{
bool bIsMean = false;
switch ( wch )
{
case L'\x0082': // BREAK PERMITTED HERE
case L'\x0083': // NO BREAK PERMITTED HERE
case L'\x00A0': // NO-BREAK SPACE
case L'\x034F': // COMBINING GRAPHEME JOINER
case L'\x2000': // EN QUAD
case L'\x2001': // EM QUAD
case L'\x2002': // EN SPACE
case L'\x2003': // EM SPACE
case L'\x2004': // THICK SPACE
case L'\x2005': // MID SPACE
case L'\x2006': // SIX SPACE
case L'\x2007': // figure space
case L'\x2008': // PUNCTUATION SPACE
case L'\x2009': // THIN SPACE
case L'\x200A': // HAIR SPACE
case L'\x200B': // ZERO-WIDTH SPACE
case L'\x200C': // ZERO-WIDTH NON-JOINER
case L'\x200D': // ZERO WIDTH JOINER
case L'\x200E': // LEFT-TO-RIGHT MARK
case L'\x2028': // LINE SEPARATOR
case L'\x2029': // PARAGRAPH SEPARATOR
case L'\x202F': // NARROW NO-BREAK SPACE
case L'\x2060': // word joiner
case L'\xFEFF': // ZERO-WIDTH NO BREAK SPACE
case L'\xFFFC': // OBJECT REPLACEMENT CHARACTER
bIsMean = true;
break;
}
return bIsMean;
}
//-----------------------------------------------------------------------------
// Purpose: Converts a UTF8 string into a unicode string
// Purpose: strips trailing whitespace; returns pointer inside string just past
// any leading whitespace.
//
// bAggresive = true causes this function to also check for "mean" spaces,
// which we don't want in persona names or chat strings as they're disruptive
// to the user experience.
//-----------------------------------------------------------------------------
static wchar_t *StripWhitespaceWorker( int cchLength, wchar_t *pwch, bool *pbStrippedWhitespace, bool bAggressive )
{
// walk backwards from the end of the string, killing any whitespace
*pbStrippedWhitespace = false;
wchar_t *pwchEnd = pwch + cchLength;
while ( --pwchEnd >= pwch )
{
if ( !iswspace( *pwchEnd ) && ( !bAggressive || !Q_IsMeanSpaceW( *pwchEnd ) ) )
break;
*pwchEnd = 0;
*pbStrippedWhitespace = true;
}
// walk forward in the string
while ( pwch < pwchEnd )
{
if ( !iswspace( *pwch ) )
break;
*pbStrippedWhitespace = true;
pwch++;
}
return pwch;
}
//-----------------------------------------------------------------------------
// Purpose: Strips all evil characters (ie. zero-width no-break space)
// from a string.
//-----------------------------------------------------------------------------
bool Q_RemoveAllEvilCharacters( char *pch )
{
// convert to unicode
int cch = Q_strlen( pch );
int cubDest = (cch + 1 ) * sizeof( wchar_t );
wchar_t *pwch = (wchar_t *)stackalloc( cubDest );
int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t );
bool bStrippedWhitespace = false;
// Walk through and skip over evil characters
int nWalk = 0;
for( int i=0; i<cwch; ++i )
{
if( !Q_IsMeanSpaceW( pwch[i] ) )
{
pwch[nWalk] = pwch[i];
++nWalk;
}
else
{
bStrippedWhitespace = true;
}
}
// Null terminate
pwch[nWalk-1] = L'\0';
// copy back, if necessary
if ( bStrippedWhitespace )
{
Q_UnicodeToUTF8( pwch, pch, cch );
}
return bStrippedWhitespace;
}
//-----------------------------------------------------------------------------
// Purpose: strips leading and trailing whitespace
//-----------------------------------------------------------------------------
bool Q_StripPrecedingAndTrailingWhitespaceW( wchar_t *pwch )
{
int cch = Q_wcslen( pwch );
// Early out and don't convert if we don't have any chars or leading/trailing ws.
if ( ( cch < 1 ) || ( !iswspace( pwch[ 0 ] ) && !iswspace( pwch[ cch - 1 ] ) ) )
return false;
// duplicate on stack
int cubDest = ( cch + 1 ) * sizeof( wchar_t );
wchar_t *pwchT = (wchar_t *)stackalloc( cubDest );
Q_wcsncpy( pwchT, pwch, cubDest );
bool bStrippedWhitespace = false;
pwchT = StripWhitespaceWorker( cch, pwch, &bStrippedWhitespace, false /* not aggressive */ );
// copy back, if necessary
if ( bStrippedWhitespace )
{
Q_wcsncpy( pwch, pwchT, cubDest );
}
return bStrippedWhitespace;
}
//-----------------------------------------------------------------------------
// Purpose: strips leading and trailing whitespace,
// and also strips punctuation and formatting characters with "clear"
// representations.
//-----------------------------------------------------------------------------
bool Q_AggressiveStripPrecedingAndTrailingWhitespaceW( wchar_t *pwch )
{
// duplicate on stack
int cch = Q_wcslen( pwch );
int cubDest = ( cch + 1 ) * sizeof( wchar_t );
wchar_t *pwchT = (wchar_t *)stackalloc( cubDest );
Q_wcsncpy( pwchT, pwch, cubDest );
bool bStrippedWhitespace = false;
pwchT = StripWhitespaceWorker( cch, pwch, &bStrippedWhitespace, true /* is aggressive */ );
// copy back, if necessary
if ( bStrippedWhitespace )
{
Q_wcsncpy( pwch, pwchT, cubDest );
}
return bStrippedWhitespace;
}
//-----------------------------------------------------------------------------
// Purpose: strips leading and trailing whitespace
//-----------------------------------------------------------------------------
bool Q_StripPrecedingAndTrailingWhitespace( char *pch )
{
int cch = Q_strlen( pch );
// Early out and don't convert if we don't have any chars or leading/trailing ws.
if ( ( cch < 1 ) || ( !isspace( (unsigned char)pch[ 0 ] ) && !isspace( (unsigned char)pch[ cch - 1 ] ) ) )
return false;
// convert to unicode
int cubDest = (cch + 1 ) * sizeof( wchar_t );
wchar_t *pwch = (wchar_t *)stackalloc( cubDest );
int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t );
bool bStrippedWhitespace = false;
pwch = StripWhitespaceWorker( cwch-1, pwch, &bStrippedWhitespace, false /* not aggressive */ );
// copy back, if necessary
if ( bStrippedWhitespace )
{
Q_UnicodeToUTF8( pwch, pch, cch );
}
return bStrippedWhitespace;
}
//-----------------------------------------------------------------------------
// Purpose: strips leading and trailing whitespace
//-----------------------------------------------------------------------------
bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch )
{
// convert to unicode
int cch = Q_strlen( pch );
int cubDest = (cch + 1 ) * sizeof( wchar_t );
wchar_t *pwch = (wchar_t *)stackalloc( cubDest );
int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t );
bool bStrippedWhitespace = false;
pwch = StripWhitespaceWorker( cwch-1, pwch, &bStrippedWhitespace, true /* is aggressive */ );
// copy back, if necessary
if ( bStrippedWhitespace )
{
Q_UnicodeToUTF8( pwch, pch, cch );
}
return bStrippedWhitespace;
}
//-----------------------------------------------------------------------------
// Purpose: Converts a ucs2 string to a unicode (wchar_t) one, no-op on win32
//-----------------------------------------------------------------------------
int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes )
{