summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/bg_lib.h9
-rw-r--r--src/ui/ui_shared.c172
2 files changed, 66 insertions, 115 deletions
diff --git a/src/game/bg_lib.h b/src/game/bg_lib.h
index d675cce4..c9ffd65b 100644
--- a/src/game/bg_lib.h
+++ b/src/game/bg_lib.h
@@ -76,6 +76,15 @@ typedef int cmp_t( const void *, const void * );
void qsort( void *a, size_t n, size_t es, cmp_t *cmp );
void srand( unsigned seed );
int rand( void );
+// FIXME: NDEBUG isn't defined for compiling the QVMs
+#ifndef NDEBUG
+#define str2(x) #x
+#define str(x) str2(x)
+#define assert(x) if(!(x)) Com_Error( ERR_DROP, \
+ __FILE__ ":" str(__LINE__) ": assertion `" #x "' failed" );
+#else
+#define assert(x)
+#endif
// String functions
size_t strlen( const char *string );
diff --git a/src/ui/ui_shared.c b/src/ui/ui_shared.c
index e708c9bb..5d883ec6 100644
--- a/src/ui/ui_shared.c
+++ b/src/ui/ui_shared.c
@@ -4539,155 +4539,97 @@ void Item_TextColor( itemDef_t *item, vec4_t *newColor )
static const char *Item_Text_Wrap( const char *text, float scale, float width )
{
- static char out[ 8192 ];
- char *paint = out;
- char startcolour[ 3 ], endcolour[ 3 ];
- const char *p = text;
- const char *eol;
- const char *q = NULL, *qMinus1 = NULL;
- unsigned int testLength;
- unsigned int i;
- int emoticonLen;
- qboolean emoticonEscaped;
+ static char out[ 8192 ] = { 0 };
+ char c[ 2 ] = { 0 };
+ const char *thisline = text;
+ size_t outlen = 0, testlen;
+ int eol = -1;
if( strlen( text ) >= sizeof( out ) )
return NULL;
- *paint = '\0';
-
- while( *p )
+ while( *thisline )
{
- Com_Memset( startcolour, 0, sizeof( startcolour ) );
- Com_Memset( endcolour, 0, sizeof( endcolour ) );
-
- // Skip leading whitespace
-
- while( *p )
+ // strip leading space and collapse colours
+ while( 1 )
{
- if( Q_IsColorString( p ) )
+ while( isspace( *thisline ) && *thisline != '\n' )
+ thisline++;
+
+ if( Q_IsColorString( thisline ) )
{
- startcolour[ 0 ] = p[ 0 ];
- startcolour[ 1 ] = p[ 1 ];
- p += 2;
+ Com_Memcpy( c, thisline, 2 );
+ thisline += 2;
}
- else if( *p != '\n' && isspace( *p ) )
- p++;
else
break;
}
- if( !*p )
+ if( !*thisline || outlen + 1 >= sizeof( out ) )
break;
- testLength = 1;
-
- eol = p;
-
- q = p;
-
- while( Q_IsColorString( q ) )
+ if( c[ 0 ] && outlen < sizeof( out ) - 3 )
{
- startcolour[ 0 ] = q[ 0 ];
- startcolour[ 1 ] = q[ 1 ];
- q += 2;
+ Com_Memcpy( &out[ outlen ], c, 2 );
+ outlen += 2;
}
- q++;
-
- while( Q_IsColorString( q ) )
+ for( testlen = 1; thisline[ testlen ] &&
+ outlen + testlen + 1 < sizeof( out ) &&
+ UI_Text_Width( thisline, scale, testlen ) < width; testlen++ )
{
- startcolour[ 0 ] = q[ 0 ];
- startcolour[ 1 ] = q[ 1 ];
- q += 2;
- }
-
- while( UI_Text_Width( p, scale, testLength ) < width )
- {
- if( testLength >= strlen( p ) )
- {
- eol = p + strlen( p );
- break;
- }
-
- // Point q at the end of the current testLength
- q = p;
-
- for( i = 0; i < testLength; )
+ // set an eol marker in the last whitespace
+ if( isspace( thisline[ testlen ] ) )
{
- // Skip color escapes
- while( Q_IsColorString( q ) )
- {
- endcolour[ 0 ] = q[ 0 ];
- endcolour[ 1 ] = q[ 1 ];
- q += 2;
- }
- while( UI_Text_Emoticon( q, &emoticonEscaped, &emoticonLen, NULL, NULL ) )
- {
- if( emoticonEscaped )
- q++;
- else
- q += emoticonLen;
- }
-
- qMinus1 = q;
- q++;
- i++;
- }
-
- // Some color escapes might still be present
- while( Q_IsColorString( q ) )
- {
- endcolour[ 0 ] = q[ 0 ];
- endcolour[ 1 ] = q[ 1 ];
- q += 2;
- }
- while( UI_Text_Emoticon( q, &emoticonEscaped, &emoticonLen, NULL, NULL ) )
- {
- if( emoticonEscaped )
- q++;
- else
- q += emoticonLen;
+ if( thisline[ eol = testlen ] == '\n' )
+ break;
+ // place the eol at the first whitespace, not spaces that follow
+ while( isspace( thisline[ testlen ] ) && thisline[ testlen ] != '\n' )
+ testlen++;
}
- // Manual line break
- if( *q == '\n' )
+ // save colour codes for restoration next line
+ if( Q_IsColorString( &thisline[ testlen ] ) )
{
- eol = q + 1;
- break;
+ Com_Memcpy( c, &thisline[ testlen ], 2 );
+ testlen++;
+ continue;
}
-
- if( !isspace( *qMinus1 ) && isspace( *q ) )
- eol = q;
-
- testLength++;
}
- // No split has taken place, so just split mid-word
- if( eol == p )
- eol = q;
-
- // Add colour code (might be empty)
- Q_strcat( out, sizeof( out ), startcolour );
+ // if we couldn't place a whitespace eol then just put it at the end
+ if( !thisline[ testlen ] || outlen + testlen + 1 == sizeof( out ) )
+ eol = testlen;
- paint = out + strlen( out );
+ // copy up the the line break
+ Com_Memcpy( &out[ outlen ], thisline, eol );
+ outlen += eol;
- // Copy text
- strncpy( paint, p, eol - p );
+ if( outlen + 1 < sizeof( out ) )
+ out[ outlen++ ] = '\n';
- paint[ eol - p ] = '\0';
-
- // Add a \n if it's not there already
- if( out[ strlen( out ) - 1 ] != '\n' )
+ // continue colour codes on the next line if there is one
+ if( c[ 0 ] && thisline[ eol ] && thisline[ eol + 1 ] &&
+ outlen + 3 < sizeof( out ) )
{
- Q_strcat( out, sizeof( out ), "\n " );
- Q_strcat( out, sizeof( out ), endcolour );
+ Com_Memcpy( &out[ outlen ], c, 2 );
+ outlen += 2;
}
+ else
+ break;
- paint = out + strlen( out );
+ thisline += eol;
- p = eol;
+ if( *thisline == '\n' )
+ thisline++;
}
+ // definitely put a newline on the end
+ if( out[ outlen - 1 ] != '\n' )
+ out[ outlen++ ] = '\n';
+
+ out[ outlen ] = '\0';
+
return out;
}