/* ================= Sys_AnsiColorPrint Transform Q3 colour codes to ANSI escape sequences ================= */ void Sys_AnsiColorPrint( const char *msg ) { static char buffer[ MAXPRINTMSG ]; int length = 0; static int q3ToAnsi[ 8 ] = { 30, // COLOR_BLACK 31, // COLOR_RED 32, // COLOR_GREEN 33, // COLOR_YELLOW 34, // COLOR_BLUE 36, // COLOR_CYAN 35, // COLOR_MAGENTA 0 // COLOR_WHITE }; while( *msg ) { if( Q_IsColorString( msg ) || *msg == '\n' ) { // First empty the buffer if( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); length = 0; } if( *msg == '\n' ) { // Issue a reset and then the newline fputs( "\033[0m\n", stderr ); msg++; } else { // Print the color code Com_sprintf( buffer, sizeof( buffer ), "\033[%dm", q3ToAnsi[ ColorIndex( *( msg + 1 ) ) ] ); fputs( buffer, stderr ); msg += 2; } } else { if( length >= MAXPRINTMSG - 1 ) break; buffer[ length ] = *msg; length++; msg++; } } // Empty anything still left in the buffer if( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); } }
/* ================= CON_WindowsColorPrint Set text colors based on Q3 color codes ================= */ void CON_WindowsColorPrint( const char *msg ) { static char buffer[ MAX_PRINT_MSG ]; int length = 0; while( *msg ) { qconsole_drawinput = ( *msg == '\n' ); if( Q_IsColorString( msg ) || *msg == '\n' ) { // First empty the buffer if( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); length = 0; } if( *msg == '\n' ) { // Reset color and then add the newline SetConsoleTextAttribute( qconsole_hout, CON_ColorCharToAttrib( COLOR_WHITE ) ); fputs( "\n", stderr ); msg++; } else { // Set the color SetConsoleTextAttribute( qconsole_hout, CON_ColorCharToAttrib( *( msg + 1 ) ) ); msg += 2; } } else { if( length >= MAX_PRINT_MSG - 1 ) break; buffer[ length ] = *msg; length++; msg++; } } // Empty anything still left in the buffer if( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); } }
/* ================= UI_DrawString2 ================= */ static void UI_DrawString2( int x, int y, const char* str, vec4_t color, int charw, int charh ) { const char* s; char ch; int forceColor = qfalse; //APSFIXME; vec4_t tempcolor; float ax; float ay; float aw; float ah; float frow; float fcol; if (y < -charh) // offscreen return; // draw the colored text trap_R_SetColor( color ); ax = x * uis.scale + uis.bias; ay = y * uis.scale; aw = charw * uis.scale; ah = charh * uis.scale; s = str; while ( *s ) { if ( Q_IsColorString( s ) ) { if ( !forceColor ) { memcpy( tempcolor, g_color_table[ColorIndex(s[1])], sizeof( tempcolor ) ); tempcolor[3] = color[3]; trap_R_SetColor( tempcolor ); } s += 2; continue; } ch = *s & 255; if (ch != ' ') { frow = (ch>>4)*0.0625; fcol = (ch&15)*0.0625; trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol + 0.0625, frow + 0.0625, uis.charset ); } ax += aw; s++; }
/* ================== SCR_DrawBigString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. Coordinates are at 640 by 480 virtual resolution ================== */ void SCR_DrawStringExt( int x, int y, float size, const char *string, qboolean forceColor, qboolean noColorEscape ) { const char *s; int xx; // draw the drop shadow re.SetColor(colorBlack); s = string; xx = x + 1; while (*s) { if ( Q_IsColorString( s ) ) { s += 2; continue; } SCR_DrawChar( xx, y+2, size, *s ); xx += size; s++; } // draw the colored text s = string; xx = x; re.SetColor( colorWhite ); while ( *s ) { if ( Q_IsColorString( s ) ) { if ( !forceColor ) { re.SetColor(ColorFromChar(s[1])); } s += 2; continue; } SCR_DrawChar( xx, y, size, *s ); xx += size; s++; } re.SetColor( NULL ); }
/* ================= CG_DrawStrlen Returns character count, skiping color escape codes ================= */ int CG_DrawStrlen( const char *str ) { const char *s = str; int count = 0; while ( *s ) { if ( Q_IsColorString( s ) ) { s += 2; } else { count++; s++; } } return count; }
/* ============== RemoveColorEscapeSequences ============== */ void RemoveColorEscapeSequences( char *text ) { int i, l; l = 0; for ( i = 0; text[i]; i++ ) { if (Q_IsColorString(&text[i])) { i++; continue; } if (text[i] > 0x7E) continue; text[l++] = text[i]; } text[l] = '\0'; }
/* ** SCR_Strlen -- skips color escape codes */ static int SCR_Strlen( const char *str ) { const char *s = str; int count = 0; const bool use102color = MV_USE102COLOR; while ( *s ) { if ( Q_IsColorString( s ) || (use102color && Q_IsColorString_1_02( s ))) { s += 2; } else { count++; s++; } } return count; }
/* ============== RemoveColorEscapeSequences ============== */ void RemoveColorEscapeSequences(char *text) { int i, l; l = 0; for (i = 0; text[i]; i++) { //Makro - don't remove underlined char escape sequence if (Q_IsColorString(&text[i]) && text[i+1]!='_') { i++; continue; } if (text[i] > 0x7E) continue; text[l++] = text[i]; } text[l] = '\0'; }
void G_DecolorString( char *in, char *out, int len ) { len--; while( *in && len > 0 ) { if( Q_IsColorString( in ) ) { in++; if( *in ) in++; continue; } *out++ = *in++; len--; } *out = '\0'; }
/** * @brief Real printable charater count */ int CG_drawStrlen(const char *str) { int cnt = 0; while (*str) { if (Q_IsColorString(str)) { str += 2; } else { cnt++; str++; } } return(cnt); }
/* ================== G_SanitiseString Remove case and control characters from a string ================== */ void G_SanitiseString( char *in, char *out, int len ) { qboolean skip = qtrue; int spaces = 0; len--; while( *in && len > 0 ) { // strip leading white space if( *in == ' ' ) { if( skip ) { in++; continue; } spaces++; } else { spaces = 0; skip = qfalse; } if( Q_IsColorString( in ) ) { in += 2; // skip color code continue; } if( *in < 32 ) { in++; continue; } *out++ = tolower( *in++ ); len--; } out -= spaces; *out = 0; }
int SCR_Text_Height(const char *text, float scale, int limit, const fontInfo_t * font) { int len, count; float max; const glyphInfo_t *glyph; float useScale; // TTimo: FIXME // const unsigned char *s = text; const char *s = text; useScale = scale * font->glyphScale; max = 0; if(text) { len = strlen(text); if(limit > 0 && len > limit) { len = limit; } count = 0; while(s && *s && count < len) { if(Q_IsColorString(s)) { s += 2; continue; } else { glyph = &font->glyphs[(int)*s]; if(max < glyph->height) { max = glyph->height; } s++; count++; } } } return max * useScale; }
char *Q_CleanStr(char *string) { char *d; char *s; int c; s = string; d = string; while ((c = *s) != 0) { if (Q_IsColorString(s)) { s++; } else if (c >= 0x20 && c <= 0x7E) { *d++ = c; } s++; } *d = '\0'; return string; }
/* ================= Q_strcpyColor - This function will return the real length of the string if numChars len of character data is desired. It looks for color codes and adds 2 to the length for each combo found. This is used to make color strings show up correctly in column formatted environments. Otherwise, the columns will be off 2 * num of color codes. ================= */ int Q_strcpyColor( const char *src, char *dest, int numChars ) { int count, len; char *d; const char *s; if( !src || !dest ) { return 0; } count = len = 0; s = src; d = dest; while( *s && count < numChars ) { if( Q_IsColorString( s )) { *d++ = *s++; *d++ = *s++; len += 2; continue; } *d = *s; s++; d++; count++; len++; } // Now fill up the end of the string with space characters if needed... while( count < numChars ) { *d = ' '; //d[len] = ' '; d++; len++; count++; } return len; }
/* Transform Q3 colour codes to ANSI escape sequences */ void Sys_AnsiColorPrint(const char *msg) { static char buffer[MAXPRINTMSG]; int length = 0; while(*msg){ if(Q_IsColorString(msg) || *msg == '\n'){ /* First empty the buffer */ if(length > 0){ buffer[length] = '\0'; fputs(buffer, stderr); length = 0; } if(*msg == '\n'){ /* Issue a reset and then the newline */ fputs("\033[0m\n", stderr); msg++; }else{ /* Print the color code */ Q_sprintf(buffer, sizeof(buffer), "\033[%dm", q3ToAnsi[ ColorIndex(*(msg + 1)) ]); fputs(buffer, stderr); msg += 2; } }else{ if(length >= MAXPRINTMSG - 1) break; buffer[length] = *msg; length++; msg++; } } /* Empty anything still left in the buffer */ if(length > 0){ buffer[length] = '\0'; fputs(buffer, stderr); } }
void UI_DrawSmallString( int x, int y, const char* str ) { vec4_t color; Vector4Set( color, 1, 1, 1, 1 ); R_SetColor( color ); while ( *str ) { if ( Q_IsColorString( str ) ) { if ( *( str + 1 ) == COLOR_NULL ) { Vector4Set( color, 1, 1, 1, 1 ); } else { Com_Memcpy( color, g_color_table[ ColorIndex( *( str + 1 ) ) ], sizeof ( color ) ); } str += 2; R_SetColor( color ); continue; } UI_SmallCharacter( x, y, *str ); str++; x += 6; } R_SetColor( NULL ); }
int Q_PrintStrlen( const char *string ) { int len; const char *p; if( !string ) { return 0; } len = 0; p = string; while( *p ) { if( Q_IsColorString( p ) ) { p += 2; continue; } p++; len++; } return len; }
int SCR_Text_Width(const char *text, float scale, int limit, const fontInfo_t * font) { int count, len; float out; const glyphInfo_t *glyph; float useScale; // FIXME: see ui_main.c, same problem // const unsigned char *s = text; const char *s = text; useScale = scale * font->glyphScale; out = 0; if(text) { len = strlen(text); if(limit > 0 && len > limit) { len = limit; } count = 0; while(s && *s && count < len) { if(Q_IsColorString(s)) { s += 2; continue; } else { glyph = &font->glyphs[(int)*s]; out += glyph->xSkip; s++; count++; } } } return out * useScale; }
/* Clean up player name to be suitable as path name. Similar to Q_CleanStr() but tweaked. */ static void SVD_CleanPlayerName(char *name) { char *src = name, *dst = name, c; while ((c = *src)) { // note Q_IsColorString(src++) won't work since it's a macro if (Q_IsColorString(src)) { src++; } else if (c == ':' || c == '\\' || c == '/' || c == '*' || c == '?') { *dst++ = '%'; } else if (c > ' ' && c < 0x7f) { *dst++ = c; } src++; } *dst = '\0'; if (strlen(name) == 0) { strcpy(name, "UnnamedPlayer"); } }
/* ================== SCR_DrawSmallString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. ================== */ void SCR_DrawSmallStringExt( int x, int y, const char *string, qboolean forceColor, qboolean noColorEscape ) { const char *s; int xx; // draw the colored text s = string; xx = x; re.SetColor(colorWhite); while (*s) { if ( Q_IsColorString( s ) ) { if (!forceColor) { re.SetColor(ColorFromChar(s[1])); } s += 2; continue; } SCR_DrawSmallChar( xx, y, *s ); xx += SMALLCHAR_WIDTH; s++; } re.SetColor( NULL ); }
/* ================= CG_DrawStrlen Returns character count, skipping color escape codes ================= */ int CG_DrawStrlen( const char *str ) { const char *s = str; int count = 0; while ( *s ) { if ( Q_IsColorString( s ) ) { s += 2; } else { /* LQ3A: Support multiline strings. */ if (*s == '\n') { break; } count++; s++; } } return count; }
/* ================== SCR_DrawSmallString[Color] Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. Coordinates are at 640 by 480 virtual resolution ================== */ void SCR_DrawSmallStringExt(int x, int y, const char *string, float *setColor, bool forceColor, bool noColorEscape ) { vec4_t color; const char *s; float xx; // draw the colored text s = string; xx = x; re.SetColor(setColor); while(*s) { if(Q_IsColorString(s)) { if(!forceColor) { if(*(s + 1) == COLOR_NULL) { memcpy(color, setColor, sizeof(color)); } else { memcpy(color, g_color_table[ColorIndex(*(s + 1))], sizeof(color)); color[3] = setColor[3]; } re.SetColor(color); } if( !noColorEscape ) { s += 2; continue; } } SCR_DrawConsoleFontChar( xx, y, *s ); xx += SCR_ConsoleFontCharWidth( *s ); s++; } re.SetColor(NULL); }
int CG_Text_Height(const char *text, float scale, int limit) { int len, count; float max; glyphInfo_t *glyph; float useScale; // TTimo: FIXME // const unsigned char *s = text; const char *s = text; fontInfo_t *font = &cgDC.Assets.textFont; if (scale <= cg_smallFont.value) { font = &cgDC.Assets.smallFont; } else if (scale > cg_bigFont.value) { font = &cgDC.Assets.bigFont; } useScale = scale * font->glyphScale; max = 0; if (text) { len = strlen(text); if (limit > 0 && len > limit) { len = limit; } count = 0; while (s && *s && count < len) { if ( Q_IsColorString(s) ) { s += 2; continue; } else { glyph = &font->glyphs[(int)*s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build if (max < glyph->height) { max = glyph->height; } s++; count++; } } } return max * useScale; }
int CG_Text_Width(const char *text, float scale, int limit) { int count,len; float out; glyphInfo_t *glyph; float useScale; // FIXME: see ui_main.c, same problem // const unsigned char *s = text; const char *s = text; fontInfo_t *font = &cgDC.Assets.textFont; if (scale <= cg_smallFont.value) { font = &cgDC.Assets.smallFont; } else if (scale > cg_bigFont.value) { font = &cgDC.Assets.bigFont; } useScale = scale * font->glyphScale; out = 0; if (text) { len = strlen(text); if (limit > 0 && len > limit) { len = limit; } count = 0; while (s && *s && count < len) { if ( Q_IsColorString(s) ) { s += 2; continue; } else { glyph = &font->glyphs[(int)*s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build out += glyph->xSkip; s++; count++; } } } return out * useScale; }
/*================== CG_DrawStringExt3 Draws a multi-colored string with a drop shadow, optionally forcing to a fixed color. Coordinates are at 640 by 480 virtual resolution ================== */ void CG_DrawStringExt3( int x, int y, const char *string, const float *setColor, qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars ) { vec4_t color; const char *s; int xx; int cnt; if ( maxChars <= 0 ) { maxChars = 32767; // do them all! } s = string; xx = 0; while ( *s ) { xx += charWidth; s++; } x -= xx; s = string; xx = x; // draw the drop shadow if ( shadow ) { color[0] = color[1] = color[2] = 0; color[3] = setColor[3]; trap_R_SetColor( color ); s = string; xx = x; cnt = 0; while ( *s && cnt < maxChars ) { if ( Q_IsColorString( s ) ) { s += 2; continue; } CG_DrawChar2( xx + ( ( charWidth < 12 ) ? 1 : 2 ), y + ( ( charHeight < 12 ) ? 1 : 2 ), charWidth, charHeight, *s ); cnt++; xx += charWidth; s++; } } // draw the colored text s = string; xx = x; cnt = 0; trap_R_SetColor( setColor ); while ( *s && cnt < maxChars ) { if ( Q_IsColorString( s ) ) { if ( !forceColor ) { if ( *( s + 1 ) == COLOR_NULL ) { memcpy( color, setColor, sizeof( color ) ); } else { memcpy( color, g_color_table[ColorIndex( *( s + 1 ) )], sizeof( color ) ); color[3] = setColor[3]; } trap_R_SetColor( color ); } s += 2; continue; } CG_DrawChar2( xx, y, charWidth, charHeight, *s ); xx += charWidth; cnt++; s++; } trap_R_SetColor( NULL ); }
/* ** Conbuf_AppendText */ void Conbuf_AppendText( const char *pMsg ) { #define CONSOLE_BUFFER_SIZE 16384 if ( !s_wcd.hWnd ) { return; } char buffer[CONSOLE_BUFFER_SIZE*4]; char *b = buffer; const char *msg; int bufLen; int i = 0; static unsigned long s_totalChars; // // if the message is REALLY long, use just the last portion of it // if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 ) { msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1; } else { msg = pMsg; } // // copy into an intermediate buffer // while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) ) { if ( msg[i] == '\n' && msg[i+1] == '\r' ) { b[0] = '\r'; b[1] = '\n'; b += 2; i++; } else if ( msg[i] == '\r' ) { b[0] = '\r'; b[1] = '\n'; b += 2; } else if ( msg[i] == '\n' ) { b[0] = '\r'; b[1] = '\n'; b += 2; } else if ( Q_IsColorString( &msg[i] ) ) { i++; } else { *b= msg[i]; b++; } i++; } *b = 0; bufLen = b - buffer; s_totalChars += bufLen; // // replace selection instead of appending if we're overflowing // if ( s_totalChars > 0x7fff ) { SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 ); s_totalChars = bufLen; } // // put this text into the windows console // SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff ); SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 ); SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer ); }
/* ======================= CG_AddToTeamChat ======================= */ static void CG_AddToTeamChat(const char *str) { int len; char *p, *ls; int lastcolor; int chatHeight; if(cg_teamChatHeight.integer < TEAMCHAT_HEIGHT) { chatHeight = cg_teamChatHeight.integer; } else { chatHeight = TEAMCHAT_HEIGHT; } if(chatHeight <= 0 || cg_teamChatTime.integer <= 0) { // team chat disabled, dump into normal chat cgs.teamChatPos = cgs.teamLastChatPos = 0; return; } len = 0; p = cgs.teamChatMsgs[cgs.teamChatPos % chatHeight]; *p = 0; lastcolor = '7'; ls = NULL; while(*str) { if(len > TEAMCHAT_WIDTH - 1) { if(ls) { str -= (p - ls); str++; p -= (p - ls); } *p = 0; cgs.teamChatMsgTimes[cgs.teamChatPos % chatHeight] = cg.time; cgs.teamChatPos++; p = cgs.teamChatMsgs[cgs.teamChatPos % chatHeight]; *p = 0; *p++ = Q_COLOR_ESCAPE; *p++ = lastcolor; len = 0; ls = NULL; } if(Q_IsColorString(str)) { *p++ = *str++; lastcolor = *str; *p++ = *str++; continue; } if(*str == ' ') { ls = p; } *p++ = *str++; len++; } *p = 0; cgs.teamChatMsgTimes[cgs.teamChatPos % chatHeight] = cg.time; cgs.teamChatPos++; if(cgs.teamChatPos - cgs.teamLastChatPos > chatHeight) cgs.teamLastChatPos = cgs.teamChatPos - chatHeight; }
/* ================= PlayerSettings_DrawName ================= */ static void PlayerSettings_DrawName(void* self) { menufield_s* f; qboolean focus; int style; char* txt; char c; float* color; int n; int basex, x, y; char name[32]; f = (menufield_s*)self; basex = f->generic.x; y = f->generic.y; focus = (f->generic.parent->cursor == f->generic.menuPosition); style = UI_LEFT | UI_SMALLFONT; color = text_color_normal; if (focus) { style |= UI_PULSE; color = text_color_highlight; } UI_DrawProportionalString(basex, y, "Name", style, color); // draw the actual name basex += 64; y += PROP_HEIGHT; txt = f->field.buffer; color = g_color_table[ColorIndex(COLOR_WHITE)]; x = basex; while ((c = *txt) != 0) { if (!focus && Q_IsColorString(txt)) { n = ColorIndex(*(txt + 1)); if (n == 0) { n = 7; } color = g_color_table[n]; txt += 2; continue; } UI_DrawChar(x, y, c, style, color); txt++; x += SMALLCHAR_WIDTH; } // draw cursor if we have focus if (focus) { if (trap_Key_GetOverstrikeMode()) { c = 11; } else { c = 10; } style &= ~UI_PULSE; style |= UI_BLINK; UI_DrawChar(basex + f->field.cursor * SMALLCHAR_WIDTH, y, c, style, color_white); } // draw at bottom also using proportional font Q_strncpyz(name, f->field.buffer, sizeof(name)); Q_CleanStr(name); UI_DrawProportionalString(320, 440, name, UI_CENTER | UI_BIGFONT, text_color_normal); }
/* ================= CON_AnsiColorPrint Transform Q3 colour codes to ANSI escape sequences ================= */ static void CON_AnsiColorPrint( const char *msg ) { static char buffer[ MAXPRINTMSG ]; int length = 0; // Approximations of g_color_table (q_math.c) #define A_BOLD 16 #define A_DIM 32 static const char colour16map[2][32] = { { // Variant 1 (xterm) 0 | A_BOLD, 1, 2, 3, 4, 6, 5, 7, 3 | A_DIM, 7 | A_DIM, 7 | A_DIM, 7 | A_DIM, 2 | A_DIM, 3 | A_DIM, 4 | A_DIM, 1 | A_DIM, 3 | A_DIM, 3 | A_DIM, 6 | A_DIM, 5 | A_DIM, 6 | A_DIM, 5 | A_DIM, 6 | A_DIM, 2 | A_BOLD, 2 | A_DIM, 1, 1 | A_DIM, 3 | A_DIM, 3 | A_DIM, 2 | A_DIM, 5, 3 | A_BOLD }, { // Variant 1 (vte) 0 | A_BOLD, 1, 2, 3 | A_BOLD, 4, 6, 5, 7, 3 , 7 | A_DIM, 7 | A_DIM, 7 | A_DIM, 2 | A_DIM, 3, 4 | A_DIM, 1 | A_DIM, 3 | A_DIM, 3 | A_DIM, 6 | A_DIM, 5 | A_DIM, 6 | A_DIM, 5 | A_DIM, 6 | A_DIM, 2 | A_BOLD, 2 | A_DIM, 1, 1 | A_DIM, 3 | A_DIM, 3 | A_DIM, 2 | A_DIM, 5, 3 | A_BOLD } }; static const char modifier[][4] = { "", ";1", ";2", "" }; int index = com_ansiColor.Get() ? 1 : 0; if ( index >= (int) ARRAY_LEN( colour16map ) ) { index = 0; } while ( *msg ) { if ( Q_IsColorString( msg ) || *msg == '\n' ) { // First empty the buffer if ( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); length = 0; } if ( *msg == '\n' ) { // Issue a reset and then the newline fputs( "\033[0;49;37m\n", stderr ); msg++; } else { // Print the color code int colour = colour16map[ index ][ ( msg[ 1 ] - '0' ) & 31 ]; Com_sprintf( buffer, sizeof( buffer ), "\033[%s%d%sm", (colour & 0x30) == 0 ? "0;" : "", 30 + ( colour & 15 ), modifier[ ( colour / 16 ) & 3 ] ); fputs( buffer, stderr ); msg += 2; } } else { if ( length >= MAXPRINTMSG - 1 ) { break; } if ( *msg == Q_COLOR_ESCAPE && msg[1] == Q_COLOR_ESCAPE ) { ++msg; } buffer[ length ] = *msg; length++; msg++; } } // Empty anything still left in the buffer if ( length > 0 ) { buffer[ length ] = '\0'; fputs( buffer, stderr ); } }
/* =========== G_ClientCleanName ============ */ static void G_ClientCleanName( const char *in, char *out, int outSize ) { int len, colorlessLen; char *p; int spaces; qboolean escaped; qboolean invalid = qfalse; //save room for trailing null byte outSize--; len = 0; colorlessLen = 0; p = out; *p = 0; spaces = 0; for( ; *in; in++ ) { // don't allow leading spaces if( colorlessLen == 0 && *in == ' ' ) continue; // don't allow nonprinting characters or (dead) console keys if( *in < ' ' || *in > '}' || *in == '`' ) continue; // check colors if( Q_IsColorString( in ) ) { in++; // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = Q_COLOR_ESCAPE; *out++ = *in; len += 2; continue; } else if( !g_emoticonsAllowedInNames.integer && G_IsEmoticon( in, &escaped ) ) { // make sure room in dest for both chars if( len > outSize - 2 ) break; *out++ = '['; *out++ = '['; len += 2; if( escaped ) in++; continue; } // don't allow too many consecutive spaces if( *in == ' ' ) { spaces++; if( spaces > 3 ) continue; } else spaces = 0; if( len > outSize - 1 ) break; *out++ = *in; colorlessLen++; len++; } *out = 0; // don't allow names beginning with "[skipnotify]" because it messes up /ignore-related code if( !Q_stricmpn( p, "[skipnotify]", 12 ) ) invalid = qtrue; // don't allow comment-beginning strings because it messes up various parsers if( strstr( p, "//" ) || strstr( p, "/*" ) ) invalid = qtrue; // don't allow empty names if( *p == 0 || colorlessLen == 0 ) invalid = qtrue; // if something made the name bad, put them back to UnnamedPlayer if( invalid ) Q_strncpyz( p, "UnnamedPlayer", outSize ); }