thirtyflightsofloving/client/cl_string.c
Knightmare66 308e1b13c4 Zero-initialize drawStruct_t in cinematic, console background, HUD field, and subimage string drawing.
Fix crash vulnerabilities in hint_test, entid, and entlist developer commands in default Lazarus and missionpack DLLs.
2021-08-22 22:12:39 -04:00

322 lines
7.6 KiB
C

/*
===========================================================================
Copyright (C) 1997-2001 Id Software, Inc.
This file is part of Quake 2 source code.
Quake 2 source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake 2 source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake 2 source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// cl_string.c
// string drawing and formatting functions
#include "client.h"
/*
================
CL_StringSetParams
================
*/
qboolean CL_StringSetParams (char modifier, int *red, int *green, int *blue, int *bold, int *shadow, int *italic, int *reset)
{
// sanity check
if (!red || !green || !blue || !bold || !shadow || !italic || !reset)
return false;
if (!alt_text_color)
alt_text_color = Cvar_Get ("alt_text_color", "2", CVAR_ARCHIVE);
switch (modifier)
{
case 'R':
case 'r':
*reset = true;
return true;
case 'B':
case 'b':
if (*bold)
*bold = false;
else
*bold = true;
return true;
case 'S':
case 's':
if (*shadow)
*shadow = false;
else
*shadow = true;
return true;
case 'I':
case 'i':
if (*italic)
*italic = false;
else
*italic = true;
return true;
case COLOR_RED:
case COLOR_GREEN:
case COLOR_YELLOW:
case COLOR_BLUE:
case COLOR_CYAN:
case COLOR_MAGENTA:
case COLOR_WHITE:
case COLOR_BLACK:
case COLOR_ORANGE:
case COLOR_GRAY:
CL_TextColor (atoi(&modifier), red, green, blue);
return true;
case 'A': // alt text color
case 'a':
// CL_TextColor ((int)alt_text_color->value, red, green, blue);
CL_TextColor (alt_text_color->integer, red, green, blue);
return true;
}
return false;
}
/*
================
CL_DrawStringGeneric
================
*/
void CL_DrawStringGeneric (int x, int y, const char *string, fontslot_t font, int alpha, int fontSize, textscaletype_t scaleType, qboolean altBit)
{
unsigned i, j;
int len, red, green, blue, italic, shadow, bold, reset;
float textSize, textScale;
byte modifier, character;
qboolean modified=false, flushChar;
// defaults
red = 255;
green = 255;
blue = 255;
italic = false;
shadow = false;
bold = false;
len = (int)strlen( string );
for ( i = 0, j = 0; i < len; i++ )
{
modifier = (byte)string[i];
if (modifier & 128) modifier &= ~128;
if (modifier == '^' && i < len)
{
i++;
reset = false;
modifier = (byte)string[i];
if (modifier & 128) modifier &= ~128;
if (modifier != '^')
{
modified = CL_StringSetParams (modifier, &red, &green, &blue, &bold, &shadow, &italic, &reset);
if ( (modifier != 'r') && (modifier != 'R') ) // fix false reset flag
reset = false;
if (reset)
{
red = 255;
green = 255;
blue = 255;
italic = false;
shadow = false;
bold = false;
}
if (modified)
continue;
else
i--;
}
}
j++;
character = (byte)string[i];
// if (bold && character < 128)
// character += 128;
// else if (bold && character > 128)
// character -= 128;
if ( (bold) || (!modified && altBit) ) {
character ^= 128;
}
// hack for alternate text color
if (!modified)
{
if (character & 128) {
// CL_TextColor ((int)alt_text_color->value, &red, &green, &blue);
CL_TextColor (alt_text_color->integer, &red, &green, &blue);
if ( (red != 255) || (green != 255) || (blue != 255) )
character &= ~128;
}
else
red = green = blue = 255;
}
switch (scaleType)
{
case SCALETYPE_MENU:
textSize = SCR_ScaledScreen(fontSize); // MENU_FONT_SIZE
textScale = SCR_GetScreenScale()*((float)fontSize/(float)MENU_FONT_SIZE);
break;
case SCALETYPE_HUD:
textSize = SCR_ScaledHud(fontSize); // HUD_FONT_SIZE
textScale = SCR_GetHudScale()*((float)fontSize/(float)HUD_FONT_SIZE);
break;
case SCALETYPE_CONSOLE:
default:
textSize = fontSize; // FONT_SIZE;
textScale = (float)fontSize/8.0f; // FONT_SIZE/8.0f
break;
}
flushChar = (i==(len-1));
if (shadow)
R_DrawChar( ( x + (j-1)*textSize+textSize/4 ), y+(textSize/8),
character, font, textScale, 0, 0, 0, alpha, italic, false );
R_DrawChar( ( x + (j-1)*textSize ), y,
character, font, textScale, red, green, blue, alpha, italic, flushChar );
}
}
/*
================
CL_DrawStringFromCharsPic
================
*/
void CL_DrawStringFromCharsPic (float x, float y, float w, float h, vec2_t offset, float width, char *string, color_t color, char *pic, int flags)
{
vec4_t modulate, shadowModulate, texCorners;
char line[1024], *l;
int len, ch;
float xx, yy, ofsX, ofsY, col, row;
char modifier;
int red, green, blue, italic, shadow, bold, reset;
qboolean modified;
drawStruct_t ds = { 0 };
Vector4Set (modulate, (float)color[0] * DIV255, (float)color[1] * DIV255, (float)color[2] * DIV255, (float)color[3] * DIV255);
Vector4Set (shadowModulate, 0, 0, 0, modulate[3]);
ofsX = w * 0.125;
ofsY = h * 0.125;
yy = y;
while (*string)
{
// Get a line of text
len = 0;
while (*string)
{
if (*string == '\n') {
string++;
break;
}
line[len++] = *string++;
if (len == sizeof(line)-1)
break;
}
line[len] = 0;
// Align the text as appropriate
if (flags & DSF_LEFT)
xx = x;
else if (flags & DSF_CENTER)
xx = x + ((width - (stringLen(line) * w)) / 2);
else if (flags & DSF_RIGHT)
xx = x + (width - (stringLen(line) * w));
else // default
xx = x;
// Convert to lower/upper case if needed
if (flags & DSF_LOWERCASE)
Q_strlwr(line);
if (flags & DSF_UPPERCASE)
Q_strupr(line);
// Draw it
l = line;
while (*l)
{
/* if (Q_IsColorString(l))
{
if (!(flags & DSF_FORCECOLOR)) {
// *(unsigned *)modulate = *(unsigned *)colorTable[Q_ColorIndex(*(l+1))];
modulate[3] = (float)color[3] * DIV255;
}
l += 2;
continue;
}*/
modifier = l[0];
if (modifier & 128) modifier &= ~128;
if (modifier == '^' && *(l+1) != 0)
{
reset = 0;
modifier = l[1];
if (modifier & 128) modifier &= ~128;
if (modifier != '^')
{
modified = CL_StringSetParams(modifier, &red, &green, &blue, &bold, &shadow, &italic, &reset);
if (reset)
red = green = blue = 255;
if (modified) {
Vector4Set (modulate, (float)red*DIV255, (float)green*DIV255, (float)blue*DIV255, modulate[3]);
l += 2;
continue;
}
}
}
ch = *l++;
ch &= 255;
ch &= ~128;
if (ch != ' ')
{
col = (ch & 15) * 0.0625;
row = (ch >> 4) * 0.0625;
Vector4Set (texCorners, col, row, col + 0.0625, row + 0.0625);
ds.pic = pic;
ds.w = w; ds.h = h;
ds.flags |= DSFLAG_USESTCOORDS;
Vector2Copy (offset, ds.offset);
Vector4Copy (texCorners, ds.stCoords);
if (flags & DSF_DROPSHADOW || shadow)
{
ds.x = xx + ofsX; ds.y = yy + ofsY;
Vector4Copy (shadowModulate, ds.color);
R_DrawPic (ds);
// R_DrawPic (xx + ofsX, yy + ofsY, w, h, offset, texCorners, shadowModulate, pic);
}
ds.x = xx; ds.y = yy;
Vector4Copy (modulate, ds.color);
R_DrawPic (ds);
// R_DrawPic (xx, yy, w, h, offset, texCorners, modulate, pic);
}
xx += w;
}
yy += h;
}
}