From f4a9eff8d316829c02220dbb4f977723614e2456 Mon Sep 17 00:00:00 2001
From: Knightmare66 <knightmare66@yahoo.com>
Date: Wed, 19 Aug 2020 02:42:15 -0400
Subject: [PATCH] Renamed cl_inv.c to cl_hud.c and moved HUD parsing/drawing
 code there from cl_screen.c. Added dumping of  configstrings to
 DumpStatusLayout command. Added temp debuging output of CS_GENERAL
 configstrings to CL_ParseConfigString().

---
 client/cl_hud.c                      | 952 +++++++++++++++++++++++++++
 client/cl_inv.c                      | 170 -----
 client/cl_parse.c                    |  50 +-
 client/cl_screen.c                   | 837 ++---------------------
 client/client.h                      |   4 +-
 client/screen.h                      |  81 ++-
 projects/VC6/kmquake2.dsp            |   4 +-
 projects/VS2005/kmquake2_2005.vcproj |   4 +-
 projects/VS2008/kmquake2_2008.vcproj |   8 +-
 9 files changed, 1060 insertions(+), 1050 deletions(-)
 create mode 100644 client/cl_hud.c
 delete mode 100644 client/cl_inv.c

diff --git a/client/cl_hud.c b/client/cl_hud.c
new file mode 100644
index 0000000..db2d381
--- /dev/null
+++ b/client/cl_hud.c
@@ -0,0 +1,952 @@
+/*
+===========================================================================
+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_hud.c -- parsing for HUD and client inventory screen
+
+#include "client.h"
+#include "../ui/ui_local.h"
+
+#define	ICON_WIDTH	24
+#define	ICON_HEIGHT	24
+#define	ICON_SPACE	8
+
+#define STAT_MINUS		10	// num frame for '-' stats digit
+char		*sb_nums[2][11] = 
+{
+	{"num_0", "num_1", "num_2", "num_3", "num_4", "num_5",
+	"num_6", "num_7", "num_8", "num_9", "num_minus"},
+	{"anum_0", "anum_1", "anum_2", "anum_3", "anum_4", "anum_5",
+	"anum_6", "anum_7", "anum_8", "anum_9", "anum_minus"}
+};
+
+//===============================================================================
+
+/*
+================
+Hud_DrawString
+================
+*/
+void Hud_DrawString (int x, int y, const char *string, int alpha, qboolean isStatusBar)
+{
+	CL_DrawStringGeneric (x, y, string, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, false);
+}
+
+
+/*
+================
+Hud_DrawStringAlt
+================
+*/
+void Hud_DrawStringAlt (int x, int y, const char *string, int alpha, qboolean isStatusBar)
+{
+	int		i, len;
+	char	highString[1024];
+
+//	Com_sprintf (highString, sizeof(highString), S_COLOR_ALT"%s", string);
+	Com_sprintf (highString, sizeof(highString), "%s", string);
+	len = (int)strlen(highString);
+	for (i=0; i<len; i++) {
+		highString[i] ^= 128;
+	}
+	CL_DrawStringGeneric (x, y, highString, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, false);
+//	CL_DrawStringGeneric (x, y, string, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, true);
+}
+
+/*
+===============================================================
+
+LAYOUT HUD CODE
+
+===============================================================
+*/
+
+/*
+================
+CL_SizeLayoutString
+
+Allow embedded \n in the string
+================
+*/
+void CL_SizeLayoutString (char *string, int *w, int *h, qboolean isStatusBar)
+{
+	int		lines, width, current;
+	float	(*scaleForScreen)(float in);
+
+	// Get our scaling function
+	if (isStatusBar)
+		scaleForScreen = SCR_ScaledHud;
+	else
+		scaleForScreen = SCR_ScaledScreen;
+
+	lines = 1;
+	width = 0;
+
+	current = 0;
+	while (*string)
+	{
+		if (*string == '\n')
+		{
+			lines++;
+			current = 0;
+		}
+		else
+		{
+			current++;
+			if (current > width)
+				width = current;
+		}
+		string++;
+	}
+
+//	*w = width * scaledHud(8);
+//	*h = lines * scaledHud(8);
+	*w = width * scaleForScreen(8);
+	*h = lines * scaleForScreen(8);
+}
+
+/*
+================
+CL_DrawLayoutString
+================
+*/
+void CL_DrawLayoutString (char *string, int x, int y, int centerwidth, int xor, qboolean isStatusBar)
+{
+	int		margin;
+	int		width, visibleWidth;
+	int		i, len;
+	char	line[1024];
+	float	(*scaleForScreen)(float in);
+
+	// Get our scaling function
+	if (isStatusBar)
+		scaleForScreen = SCR_ScaledHud;
+	else
+		scaleForScreen = SCR_ScaledScreen;
+
+	margin = x;
+
+//	len = strlen(string);
+
+	while (*string)
+	{
+		// scan out one line of text from the string
+		width = 0;
+		while (*string && *string != '\n')
+			line[width++] = *string++;
+
+		line[width] = 0;
+		visibleWidth = stringLen(line);
+
+		if (centerwidth)
+		//	x = margin + (centerwidth - width*scaledHud(8))/2;
+		//	x = margin + (centerwidth - width*scaleForScreen(8))/2;
+			x = margin + (centerwidth - visibleWidth*scaleForScreen(8))/2;
+		else
+			x = margin;
+
+
+		if (xor)
+		{	// Knightmare- text color hack
+		//	Com_sprintf (line, sizeof(line), S_COLOR_ALT"%s", line);
+			len = (int)strlen(line);
+			for (i=0; i<len; i++) {
+				line[i] ^= xor;
+			}
+		}
+		Hud_DrawString (x, y, line, 255, isStatusBar);
+
+		if (*string)
+		{
+			string++;	// skip the \n
+			x = margin;
+		//	y += scaledHud(8);
+			y += scaleForScreen(8);
+		}
+	}
+}
+
+
+/*
+==============
+CL_DrawLayoutField
+
+Draws HUD number displays
+==============
+*/
+void CL_DrawLayoutField (int x, int y, int color, int width, int value, qboolean flash, qboolean isStatusBar)
+{
+	char		num[16], *ptr;
+	int			l, frame;
+	float		digitWidth, digitOffset, fieldScale;
+	float		flash_x, flashWidth;
+	float		(*scaleForScreen)(float in);
+	float		(*getScreenScale)(void);
+
+	if (width < 1)
+		return;
+
+	// Get our scaling functions
+	if (isStatusBar) {
+		scaleForScreen = SCR_ScaledHud;
+		getScreenScale = SCR_GetHudScale;
+	}
+	else {
+		scaleForScreen = SCR_ScaledScreen;
+		getScreenScale = SCR_GetScreenScale;
+	}
+
+	// draw number string
+	fieldScale = getScreenScale();
+	if (width > 5)
+		width = 5;
+
+	Com_sprintf (num, sizeof(num), "%i", value);
+	l = (int)strlen(num);
+	if (l > width)
+	{
+	//	if (scr_hudsqueezedigits->value) {
+		if (scr_hudsqueezedigits->integer) {
+			l = min(l, width+2);
+			fieldScale =  (1.0 - ((1.0 - (float)width/(float)l) * 0.5)) * getScreenScale();
+		}
+		else
+			l = width;
+	}
+	digitWidth = fieldScale*(float)CHAR_WIDTH;
+	digitOffset = width*scaleForScreen(CHAR_WIDTH) - l*digitWidth;
+//	x += 2 + scaledHud(CHAR_WIDTH)*(width - l);
+//	x += 2 + scaleForScreen(CHAR_WIDTH)*(width - l);
+	x += 2 + digitOffset;
+	flashWidth = l*digitWidth;
+	flash_x = x;
+
+	if (flash)
+		R_DrawStretchPic (flash_x, y, flashWidth, scaleForScreen(ICON_HEIGHT), "field_3", scr_hudalpha->value);
+
+	ptr = num;
+	while (*ptr && l)
+	{
+		if (*ptr == '-')
+			frame = STAT_MINUS;
+		else
+			frame = *ptr -'0';
+
+//		R_DrawScaledPic (x, y, HudScale(), scr_hudalpha->value,sb_nums[color][frame]);
+//		x += scaledHud(CHAR_WIDTH);
+//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, sb_nums[color][frame]);
+//		x += scaleForScreen(CHAR_WIDTH);
+		R_DrawStretchPic (x, y, digitWidth, scaleForScreen(ICON_HEIGHT), sb_nums[color][frame], scr_hudalpha->value);
+		x += digitWidth;
+		ptr++;
+		l--;
+	}
+}
+
+
+/*
+================
+CL_ExecuteLayoutString 
+================
+*/
+void CL_ExecuteLayoutString (char *s, qboolean isStatusBar)
+{
+	int		x, y;
+	int		value, stat, width, index, cs_images, max_images;
+	char	*token;
+	clientinfo_t	*ci;
+	float			(*scaleForScreen)(float in);
+	float			(*getScreenScale)(void);
+	float			scrLeft, scrWidth;
+
+	if (cls.state != ca_active || !cl.refresh_prepped)
+		return;
+
+	if (!s[0])
+		return;
+
+	// Knightmare- hack for connected to server using old protocol
+	// Changed config strings require different parsing
+	if ( LegacyProtocol() ) {
+		cs_images = OLD_CS_IMAGES;
+		max_images = OLD_MAX_IMAGES;
+	}
+	else {
+		cs_images = CS_IMAGES;
+		max_images = MAX_IMAGES;
+	}
+
+	// Get our scaling functions
+	if (isStatusBar) {
+		scaleForScreen = SCR_ScaledHud;
+		getScreenScale = SCR_GetHudScale;
+	}
+	else {
+		scaleForScreen = SCR_ScaledScreen;
+		getScreenScale = SCR_GetScreenScale;
+	}
+
+	SCR_InitHudScale ();
+	x = 0;
+	y = 0;
+	width = 3;
+
+	scrLeft = 0;
+	scrWidth = SCREEN_WIDTH;
+	SCR_AdjustFrom640 (&scrLeft, NULL, &scrWidth, NULL, ALIGN_STRETCH);
+
+	while (s)
+	{
+		token = COM_Parse (&s);
+		if (!strcmp(token, "xl"))
+		{
+			token = COM_Parse (&s);
+		//	x = scaleForScreen(atoi(token));
+			x = (int)scrLeft + scaleForScreen(atoi(token));
+			continue;
+		}
+		if (!strcmp(token, "xr"))
+		{
+			token = COM_Parse (&s);
+		//	x = viddef.width + scaleForScreen(atoi(token));
+			x = (int)(scrLeft + scrWidth) + scaleForScreen(atoi(token));
+			continue;
+		}
+		if (!strcmp(token, "xv"))
+		{
+			token = COM_Parse (&s);
+			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
+			continue;
+		}
+		if (!strcmp(token, "yt"))
+		{
+			token = COM_Parse (&s);
+			y = scaleForScreen(atoi(token));
+			continue;
+		}
+		if (!strcmp(token, "yb"))
+		{
+			token = COM_Parse (&s);
+			y = viddef.height + scaleForScreen(atoi(token));
+			continue;
+		}
+		if (!strcmp(token, "yv"))
+		{
+			token = COM_Parse (&s);
+			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
+			continue;
+		}
+
+		if (!strcmp(token, "pic"))
+		{	// draw a pic from a stat number
+			token = COM_Parse (&s);
+		//	value = cl.frame.playerstate.stats[atoi(token)];
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
+				Com_Error (ERR_DROP, "Bad pic stat index");
+			value = cl.frame.playerstate.stats[stat];
+			if (value >= max_images) // Knightmare- don't bomb out
+			//	Com_Error (ERR_DROP, "Pic >= MAX_IMAGES");
+			{
+				Com_Printf (S_COLOR_YELLOW"WARNING: Pic >= MAX_IMAGES\n");
+				value = max_images-1;
+			}
+			if (cl.configstrings[cs_images+value])
+			{
+				R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, cl.configstrings[cs_images+value]);
+			}
+			continue;
+		}
+
+		if (!strcmp(token, "client"))
+		{	// draw a deathmatch client block
+			int		score, ping, time;
+
+			token = COM_Parse (&s);
+			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
+			token = COM_Parse (&s);
+			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
+
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (value >= MAX_CLIENTS || value < 0)
+				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
+			ci = &cl.clientinfo[value];
+
+			token = COM_Parse (&s);
+			score = atoi(token);
+
+			token = COM_Parse (&s);
+			ping = atoi(token);
+
+			token = COM_Parse (&s);
+			time = atoi(token);
+
+			Hud_DrawStringAlt (x+scaleForScreen(32), y, va(S_COLOR_ALT"%s", ci->name), 255, isStatusBar);
+			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(8),  "Score: ", 255, isStatusBar);
+			Hud_DrawStringAlt (x+scaleForScreen(32+7*8), y+scaleForScreen(8),  va(S_COLOR_ALT"%i", score), 255, isStatusBar);
+			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(16), va("Ping:  %i", ping), 255, isStatusBar);
+			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(24), va("Time:  %i", time), 255, isStatusBar);
+
+			if (!ci->icon)
+				ci = &cl.baseclientinfo;
+			R_DrawScaledPic(x, y, getScreenScale(), scr_hudalpha->value,  ci->iconname);
+			continue;
+		}
+
+		if (!strcmp(token, "ctf"))
+		{	// draw a ctf client block
+			int		score, ping;
+			char	block[80];
+
+			token = COM_Parse (&s);
+			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
+			token = COM_Parse (&s);
+			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
+
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (value >= MAX_CLIENTS || value < 0)
+				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
+			ci = &cl.clientinfo[value];
+
+			token = COM_Parse (&s);
+			score = atoi(token);
+
+			token = COM_Parse (&s);
+			ping = atoi(token);
+			if (ping > 999)
+				ping = 999;
+
+			sprintf(block, "%3d %3d %-12.12s", score, ping, ci->name);
+
+			if (value == cl.playernum)
+				Hud_DrawStringAlt (x, y, block, 255, isStatusBar);
+			else
+				Hud_DrawString (x, y, block, 255, isStatusBar);
+			continue;
+		}
+		
+		if (!strcmp(token, "3tctf")) // Knightmare- 3Team CTF block
+		{	// draw a 3Team CTF client block
+			int		score, ping;
+			char	block[80];
+
+			token = COM_Parse (&s);
+			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
+			token = COM_Parse (&s);
+			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
+
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (value >= MAX_CLIENTS || value < 0)
+				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
+			ci = &cl.clientinfo[value];
+
+			token = COM_Parse (&s);
+			score = atoi(token);
+
+			token = COM_Parse (&s);
+			ping = atoi(token);
+			if (ping > 999)
+				ping = 999;
+			// double spaced before player name for 2 flag icons
+			sprintf(block, "%3d %3d  %-12.12s", score, ping, ci->name);
+
+			if (value == cl.playernum)
+				Hud_DrawStringAlt (x, y, block, 255, isStatusBar);
+			else
+				Hud_DrawString (x, y, block, 255, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "picn"))
+		{	// draw a pic from a name
+			token = COM_Parse (&s);
+			R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, token);
+			continue;
+		}
+
+		if (!strcmp(token, "num"))
+		{	// draw a number
+			token = COM_Parse (&s);
+			width = atoi(token);
+			token = COM_Parse (&s);
+		//	value = cl.frame.playerstate.stats[atoi(token)];
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
+				Com_Error (ERR_DROP, "Bad num stat index");
+			value = cl.frame.playerstate.stats[stat];
+			CL_DrawLayoutField (x, y, 0, width, value, false, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "hnum"))
+		{	// health number
+			int		color;
+
+			width = 3;
+			value = cl.frame.playerstate.stats[STAT_HEALTH];
+			if (value > 25)
+				color = 0;	// green
+			else if (value > 0)
+				color = (cl.frame.serverframe>>2) & 1;		// flash
+			else
+				color = 1;
+
+		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 1)
+		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
+
+			CL_DrawLayoutField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 1), isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "anum"))
+		{	// ammo number
+			int		color;
+
+			width = 3;
+			value = cl.frame.playerstate.stats[STAT_AMMO];
+			if (value > 5)
+				color = 0;	// green
+			else if (value >= 0)
+				color = (cl.frame.serverframe>>2) & 1;		// flash
+			else
+				continue;	// negative number = don't show
+
+		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 4)
+		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
+
+			CL_DrawLayoutField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 4), isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "rnum"))
+		{	// armor number
+			int		color;
+
+			width = 3;
+			value = cl.frame.playerstate.stats[STAT_ARMOR];
+			if (value < 1)
+				continue;
+
+			color = 0;	// green
+
+		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 2)
+		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
+
+			CL_DrawLayoutField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 2), isStatusBar);
+			continue;
+		}
+
+
+		if (!strcmp(token, "stat_string"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)	// MAX_CONFIGSTRINGS
+				Com_Error (ERR_DROP, "Bad stat_string stat index");
+			index = cl.frame.playerstate.stats[stat];
+			if (index < 0 || index >= MAX_CONFIGSTRINGS)
+				Com_Error (ERR_DROP, "Bad stat_string configstring index");
+			Hud_DrawString (x, y, cl.configstrings[index], 255, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "cstring"))
+		{
+			token = COM_Parse (&s);
+			CL_DrawLayoutString (token, x, y, scaleForScreen(320), 0, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "string"))
+		{
+			token = COM_Parse (&s);
+			Hud_DrawString (x, y, token, 255, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "cstring2"))
+		{
+			token = COM_Parse (&s);
+			CL_DrawLayoutString (token, x, y, scaleForScreen(320), 0x80, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "string2"))
+		{
+			token = COM_Parse (&s);
+			Hud_DrawStringAlt (x, y, token, 255, isStatusBar);
+			continue;
+		}
+
+		if (!strcmp(token, "if"))
+		{	// draw a number
+			token = COM_Parse (&s);
+		//	value = cl.frame.playerstate.stats[atoi(token)];
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
+				Com_Error (ERR_DROP, "Bad if stat index");
+			value = cl.frame.playerstate.stats[stat];
+			if (!value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}
+			}
+
+			continue;
+		}
+
+		// ifeq <stat> <value>
+		// ifbit <stat> <value>
+
+		// Knightmare- added more commands
+		if (!strcmp(token, "ifeq"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifeq stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] != value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifneq"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifneq stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] == value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifgt"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifgt stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] <= value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifge"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifge stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] < value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "iflt"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad iflt stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] >= value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifle"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifle stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (cl.frame.playerstate.stats[stat] > value)
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifbit"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifbit stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (value < 1 || value > 16)
+				Com_Error (ERR_DROP, "Bad ifbit bit value");
+			if ( !(cl.frame.playerstate.stats[stat] & (1<<(value-1))) )
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+
+		if (!strcmp(token, "ifnbit"))
+		{
+			token = COM_Parse (&s);
+			stat = atoi(token);
+			if (stat < 0 || stat >= MAX_STATS)
+				Com_Error (ERR_DROP, "Bad ifnbit stat index");
+			token = COM_Parse (&s);
+			value = atoi(token);
+			if (value < 1 || value > 16)
+				Com_Error (ERR_DROP, "Bad ifnbit bit value");
+			if ( cl.frame.playerstate.stats[stat] & (1<<(value-1)) )
+			{	// skip to endif
+				while (s && strcmp(token, "endif") )
+				{
+					token = COM_Parse (&s);
+				}			
+			}
+		}
+		// end Knightmare
+	}
+}
+
+
+/*
+================
+CL_DrawStatus
+
+The status bar is a small layout program that
+is based on the stats array
+================
+*/
+void CL_DrawStatus (void)
+{
+	CL_ExecuteLayoutString (cl.configstrings[CS_STATUSBAR], true);
+}
+
+
+/*
+================
+CL_DrawLayout
+
+================
+*/
+#define	STAT_LAYOUTS		13
+
+void CL_DrawLayout (void)
+{
+	qboolean isStatusBar = false;
+
+	if (!cl.frame.playerstate.stats[STAT_LAYOUTS])
+		return;
+
+	// Special hack for visor HUD addition in Zaero
+	if ( strstr(cl.layout, "\"Tracking ") )
+		isStatusBar = true;
+
+	CL_ExecuteLayoutString (cl.layout, isStatusBar);
+}
+
+/*
+===============================================================
+
+INVENTORY CODE
+
+===============================================================
+*/
+
+/*
+================
+CL_ParseInventory
+================
+*/
+void CL_ParseInventory (void)
+{
+	int		i, max_items;
+
+	// Knightmare- hack for connected to server using old protocol
+	// Changed config strings require different parsing
+	if ( LegacyProtocol() )
+		max_items = OLD_MAX_ITEMS;
+	else
+		max_items = MAX_ITEMS;
+
+	for (i = 0; i < max_items; i++)
+		cl.inventory[i] = MSG_ReadShort (&net_message);
+}
+
+
+/*
+================
+CL_DrawInventory
+================
+*/
+#define	DISPLAY_ITEMS	17
+
+void CL_DrawInventory (void)
+{
+	int		i, j;
+	int		num, selected_num, item;
+	int		index[MAX_ITEMS];
+	char	string[1024];
+	int		x, y;
+	char	binding[1024];
+	char	*bind;
+	int		selected;
+	int		top;
+
+	selected = cl.frame.playerstate.stats[STAT_SELECTED_ITEM];
+
+	num = 0;
+	selected_num = 0;
+	for (i=0; i<MAX_ITEMS; i++)
+	{
+		if (i==selected)
+			selected_num = num;
+		if (cl.inventory[i])
+		{
+			index[num] = i;
+			num++;
+		}
+	}
+
+	// determine scroll point
+	top = selected_num - DISPLAY_ITEMS/2;
+	if (num - top < DISPLAY_ITEMS)
+		top = num - DISPLAY_ITEMS;
+	if (top < 0)
+		top = 0;
+
+	//x = (viddef.width-256)/2;
+	//y = (viddef.height-240)/2;
+//	x = viddef.width/2 - SCR_ScaledHud(128);
+//	y = viddef.height/2 - SCR_ScaledHud(120);
+	x = SCREEN_WIDTH/2 - 128;
+	y = SCREEN_HEIGHT/2 - 116;
+
+//	R_DrawScaledPic (x, y+SCR_ScaledHud(8), SCR_GetHudScale(), scr_hudalpha->value, "inventory");
+//	y += SCR_ScaledHud(24);
+//	x += SCR_ScaledHud(24);
+//	Hud_DrawString (x, y, S_COLOR_BOLD"hotkey ### item");
+//	Hud_DrawString (x, y+SCR_ScaledHud(8), S_COLOR_BOLD"------ --- ----");
+//	y += SCR_ScaledHud(16);
+	SCR_DrawPic (x, y, 256, 192, ALIGN_CENTER, "inventory", scr_hudalpha->value);
+	x += 24;
+	y += 20;
+	SCR_DrawString (x, y, 8, ALIGN_CENTER, S_COLOR_WHITE"hotkey ### item", 255);
+	y += 8;
+	SCR_DrawString (x, y, 8, ALIGN_CENTER, S_COLOR_WHITE"------ --- ----", 255);
+	x += 16;
+	y += 8;
+
+	for (i=top; i<num && i < top+DISPLAY_ITEMS; i++)
+	{
+		item = index[i];
+		// search for a binding
+
+		// Knightmare- BIG UGLY HACK for connected to server using old protocol
+		// Changed config strings require different parsing
+		if ( LegacyProtocol() )
+			Com_sprintf (binding, sizeof(binding), "use %s", cl.configstrings[OLD_CS_ITEMS+item]);
+		else
+			Com_sprintf (binding, sizeof(binding), "use %s", cl.configstrings[CS_ITEMS+item]);
+
+		bind = "";
+		for (j=0; j<256; j++)
+			if (keybindings[j] && !Q_stricmp (keybindings[j], binding))
+			{
+				bind = Key_KeynumToString(j);
+				break;
+			}
+
+		// Knightmare- BIG UGLY HACK for connected to server using old protocol
+		// Changed config strings require different parsing
+		if ( LegacyProtocol() )
+		{
+			if (item != selected)
+			{
+				Com_sprintf (string, sizeof(string), " "S_COLOR_ALT"%3s %3i %7s", bind, cl.inventory[item],
+					cl.configstrings[OLD_CS_ITEMS+item] );
+			}
+			else	// draw a blinky cursor by the selected item
+			{
+				Com_sprintf (string, sizeof(string), S_COLOR_WHITE">"S_COLOR_ITALIC"%3s %3i %7s", bind, cl.inventory[item],
+					cl.configstrings[OLD_CS_ITEMS+item] );
+			}
+		}
+		else
+		{
+			if (item != selected)
+			{
+				Com_sprintf (string, sizeof(string), " "S_COLOR_ALT"%3s %3i %7s", bind, cl.inventory[item],
+					cl.configstrings[CS_ITEMS+item] );
+			}
+			else	// draw a blinky cursor by the selected item
+			{
+				Com_sprintf (string, sizeof(string), S_COLOR_WHITE">"S_COLOR_ITALIC"%3s %3i %7s", bind, cl.inventory[item],
+					cl.configstrings[CS_ITEMS+item] );
+			}
+		}
+
+	//	Hud_DrawString (x, y, string);
+	//	y += SCR_ScaledHud(8);
+		SCR_DrawString (x, y, 8, ALIGN_CENTER, string, 255);
+		y += 8;
+	}
+
+}
diff --git a/client/cl_inv.c b/client/cl_inv.c
deleted file mode 100644
index 6381a28..0000000
--- a/client/cl_inv.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-===========================================================================
-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_inv.c -- client inventory screen
-
-#include "client.h"
-
-void Hud_DrawString (int x, int y, int size, const char *string, int alpha, qboolean isStatusBar);
-
-/*
-================
-CL_ParseInventory
-================
-*/
-void CL_ParseInventory (void)
-{
-	int		i;
-
-	for (i = 0; i < MAX_ITEMS; i++)
-		cl.inventory[i] = MSG_ReadShort (&net_message);
-}
-
-
-void SetStringHighBit (char *s)
-{
-	while (*s)
-		*s++ |= 128;
-}
-
-
-/*
-================
-CL_DrawInventory
-================
-*/
-#define	DISPLAY_ITEMS	17
-
-void CL_DrawInventory (void)
-{
-	int		i, j;
-	int		num, selected_num, item;
-	int		index[MAX_ITEMS];
-	char	string[1024];
-	int		x, y;
-	char	binding[1024];
-	char	*bind;
-	int		selected;
-	int		top;
-
-	selected = cl.frame.playerstate.stats[STAT_SELECTED_ITEM];
-
-	num = 0;
-	selected_num = 0;
-	for (i=0; i<MAX_ITEMS; i++)
-	{
-		if (i==selected)
-			selected_num = num;
-		if (cl.inventory[i])
-		{
-			index[num] = i;
-			num++;
-		}
-	}
-
-	// determine scroll point
-	top = selected_num - DISPLAY_ITEMS/2;
-	if (num - top < DISPLAY_ITEMS)
-		top = num - DISPLAY_ITEMS;
-	if (top < 0)
-		top = 0;
-
-	//x = (viddef.width-256)/2;
-	//y = (viddef.height-240)/2;
-//	x = viddef.width/2 - SCR_ScaledHud(128);
-//	y = viddef.height/2 - SCR_ScaledHud(120);
-	x = SCREEN_WIDTH/2 - 128;
-	y = SCREEN_HEIGHT/2 - 116;
-
-//	R_DrawScaledPic (x, y+SCR_ScaledHud(8), SCR_GetHudScale(), scr_hudalpha->value, "inventory");
-//	y += SCR_ScaledHud(24);
-//	x += SCR_ScaledHud(24);
-//	Hud_DrawString (x, y, S_COLOR_BOLD"hotkey ### item");
-//	Hud_DrawString (x, y+SCR_ScaledHud(8), S_COLOR_BOLD"------ --- ----");
-//	y += SCR_ScaledHud(16);
-	SCR_DrawPic (x, y, 256, 192, ALIGN_CENTER, "inventory", scr_hudalpha->value);
-	x += 24;
-	y += 20;
-	SCR_DrawString (x, y, 8, ALIGN_CENTER, S_COLOR_WHITE"hotkey ### item", 255);
-	y += 8;
-	SCR_DrawString (x, y, 8, ALIGN_CENTER, S_COLOR_WHITE"------ --- ----", 255);
-	x += 16;
-	y += 8;
-
-	for (i=top; i<num && i < top+DISPLAY_ITEMS; i++)
-	{
-		item = index[i];
-		// search for a binding
-
-		// Knightmare- BIG UGLY HACK for connected to server using old protocol
-		// Changed config strings require different parsing
-		if ( LegacyProtocol() )
-			Com_sprintf (binding, sizeof(binding), "use %s", cl.configstrings[OLD_CS_ITEMS+item]);
-		else
-			Com_sprintf (binding, sizeof(binding), "use %s", cl.configstrings[CS_ITEMS+item]);
-
-		bind = "";
-		for (j=0; j<256; j++)
-			if (keybindings[j] && !Q_stricmp (keybindings[j], binding))
-			{
-				bind = Key_KeynumToString(j);
-				break;
-			}
-
-		// Knightmare- BIG UGLY HACK for connected to server using old protocol
-		// Changed config strings require different parsing
-		if ( LegacyProtocol() )
-		{
-			if (item != selected)
-			{
-				Com_sprintf (string, sizeof(string), " "S_COLOR_ALT"%3s %3i %7s", bind, cl.inventory[item],
-					cl.configstrings[OLD_CS_ITEMS+item] );
-			}
-			else	// draw a blinky cursor by the selected item
-			{
-				Com_sprintf (string, sizeof(string), S_COLOR_WHITE">"S_COLOR_ITALIC"%3s %3i %7s", bind, cl.inventory[item],
-					cl.configstrings[OLD_CS_ITEMS+item] );
-			}
-		}
-		else
-		{
-			if (item != selected)
-			{
-				Com_sprintf (string, sizeof(string), " "S_COLOR_ALT"%3s %3i %7s", bind, cl.inventory[item],
-					cl.configstrings[CS_ITEMS+item] );
-			}
-			else	// draw a blinky cursor by the selected item
-			{
-				Com_sprintf (string, sizeof(string), S_COLOR_WHITE">"S_COLOR_ITALIC"%3s %3i %7s", bind, cl.inventory[item],
-					cl.configstrings[CS_ITEMS+item] );
-			}
-		}
-
-//		Hud_DrawString (x, y, string);
-//		y += SCR_ScaledHud(8);
-		SCR_DrawString (x, y, 8, ALIGN_CENTER, string, 255);
-		y += 8;
-	}
-
-}
-
-
diff --git a/client/cl_parse.c b/client/cl_parse.c
index 97e7c64..b86f972 100644
--- a/client/cl_parse.c
+++ b/client/cl_parse.c
@@ -502,10 +502,12 @@ void CL_ParseConfigString (void)
 	else if ( LegacyProtocol() && (i >= OLD_CS_GENERAL && i < OLD_MAX_CONFIGSTRINGS) ) {	// allow writes to general strings to overflow
 		strncpy (cl.configstrings[i], s, (sizeof(cl.configstrings[i]) * (OLD_MAX_CONFIGSTRINGS - i))-1 );
 		cl.configstrings[OLD_MAX_CONFIGSTRINGS-1][MAX_QPATH-1] = 0;	// null terminate end of section
+		Com_Printf("CL_ParseConfigString: CS_GENERAL %i: '%s', maxlen=%i\n", i, s, (sizeof(cl.configstrings[i]) * (OLD_MAX_CONFIGSTRINGS - i))-1);	// FIXME: remove this!
 	}
 	else if ( !LegacyProtocol() && (i >= CS_GENERAL && i < CS_PAKFILE) ) {	// allow writes to general strings to overflow
 		strncpy (cl.configstrings[i], s, (sizeof(cl.configstrings[i]) * (CS_PAKFILE - i))-1 );
 		cl.configstrings[CS_PAKFILE-1][MAX_QPATH-1] = 0;	// null terminate end of section
+		Com_Printf("CL_ParseConfigString: CS_GENERAL %i: '%s', maxlen=%i\n", i, s, (sizeof(cl.configstrings[i]) * (CS_PAKFILE - i))-1);	// FIXME: remove this!
 	}
 	else {
 		if (length >= MAX_QPATH)
@@ -752,7 +754,6 @@ qboolean CL_FilterStuffText (char *stufftext, size_t textSize)
 	if ( !stufftext || (stuffLen == 0) )
 		return true;
 
-#if 1
 	do
 	{
 		if ( ((parsetext - stufftext) >= (textSize-1)) || ((parsetext - stufftext) >= stuffLen) )
@@ -830,54 +831,7 @@ qboolean CL_FilterStuffText (char *stufftext, size_t textSize)
 		}
 		parsetext = p;
 	} while (parsetext != NULL);
-#else
-	// skip leading spaces
-	while (*parsetext == ' ') parsetext++;
 
-	// handle quit and error stuffs specially
-	if (!strncmp(parsetext, "quit", 4) || !strncmp(parsetext, "error", 5))
-	{
-		Com_Printf(S_COLOR_YELLOW"CL_FilterStuffText: Server stuffed 'quit' or 'error' command, disconnecting...\n");
-		CL_Disconnect ();
-		return false;
-	}
-
-	// don't allow stuffing of renderer cvars
-	if ( !strncmp(parsetext, "gl_", 3) || !strncmp(parsetext, "r_", 2) )    	
-		return false;
-
-	// the Generations mod stuffs exec g*.cfg  for classes, so limit exec stuffs to .cfg files
-	if ( !strncmp(parsetext, "exec", 4) )
-	{
-		s = parsetext;
-		execname = COM_Parse (&s);
-		if (!s) {
-			Com_Printf(S_COLOR_YELLOW"CL_FilterStuffText: Server stuffed 'exec' command with no file\n");
-			return false;	// catch case of no text after 'exec'
-		}
-
-		execname = COM_Parse (&s);
-		execLen = (int)strlen(execname);
-
-		if ( (execLen > 1) && (execname[execLen-1] == ';') )	// catch token ending with ;
-			execLen--;
-
-		if ( (execLen < 5) || (strncmp(execname+execLen-4, ".cfg", 4) != 0) ) {
-			Com_Printf(S_COLOR_YELLOW"CL_FilterStuffText: Server stuffed 'exec' command for non-cfg file\n");
-			return false;
-		}
-		return true;
-	}
-
-	// code by xian- cycle through list of malicious commands
-	i = 0;
-	while (bad_stuffcmds[i] != NULL)
-	{
-		if ( Q_StrScanToken(parsetext, bad_stuffcmds[i], true) )
-			return false;
-		i++;
-	}
-#endif
 	return true;
 }
 
diff --git a/client/cl_screen.c b/client/cl_screen.c
index 45d7266..283492a 100644
--- a/client/cl_screen.c
+++ b/client/cl_screen.c
@@ -103,10 +103,6 @@ void SCR_Loading_f (void);
 
 #define LOADSCREEN_NAME "/gfx/ui/unknownmap.pcx"
 
-#define	ICON_WIDTH	24
-#define	ICON_HEIGHT	24
-#define	CHAR_WIDTH	16
-#define	ICON_SPACE	8
 
 /*
 ===============================================================
@@ -668,39 +664,6 @@ void SCR_DrawString (float x, float y, int size, scralign_t align, const char *s
 
 //===============================================================================
 
-
-/*
-================
-Hud_DrawString
-================
-*/
-void Hud_DrawString (int x, int y, const char *string, int alpha, qboolean isStatusBar)
-{
-	CL_DrawStringGeneric (x, y, string, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, false);
-}
-
-
-/*
-================
-Hud_DrawStringAlt
-================
-*/
-void Hud_DrawStringAlt (int x, int y, const char *string, int alpha, qboolean isStatusBar)
-{
-	int		i, len;
-	char	highString[1024];
-
-//	Com_sprintf (highString, sizeof(highString), S_COLOR_ALT"%s", string);
-	Com_sprintf (highString, sizeof(highString), "%s", string);
-	len = (int)strlen(highString);
-	for (i=0; i<len; i++) {
-		highString[i] ^= 128;
-	}
-	CL_DrawStringGeneric (x, y, highString, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, false);
-//	CL_DrawStringGeneric (x, y, string, alpha, HUD_FONT_SIZE, (isStatusBar) ? SCALETYPE_HUD : SCALETYPE_MENU, true);
-}
-
-
 /*
 ================
 SCR_ShowFPS
@@ -1164,12 +1127,18 @@ Saves the statusbar layout to a file
 */
 void SCR_DumpStatusLayout_f (void)
 {
-	char	buffer[2048], rawLine[MAX_QPATH+1], statLine[32];
-	int		i, j, bufcount;
+	char	buffer[2048], rawLine[MAX_QPATH+1], formatLine[80], statLine[32];
+	int		i, j, cs_general, bufcount = 0;
 	FILE	*f;
 	char	*p;
 	char	name[MAX_OSPATH];
 
+	// starting index is based on protocol for CS_GENERAL section
+	if ( LegacyProtocol() )
+		cs_general = OLD_CS_GENERAL;
+	else
+		cs_general = CS_GENERAL;
+
 	if (Cmd_Argc() != 2)
 	{
 		Com_Printf ("usage: dumpstatuslayout <filename>\n");
@@ -1188,6 +1157,12 @@ void SCR_DumpStatusLayout_f (void)
 
 	// statusbar layout is in multiple configstrings
 	// starting at CS_STATUSBAR and ending at CS_AIRACCEL
+	Com_sprintf(formatLine, sizeof(formatLine), "\nFormatted Dump\n--------------\n");
+	Q_strncatz (buffer, formatLine, sizeof(buffer));
+	bufcount += (int)strlen(formatLine);
+	fwrite(&buffer, 1, bufcount, f);
+	buffer[0] = 0;
+	bufcount = 0;
 	p = &buffer[0];
 	bufcount = 0;
 	for (i=CS_STATUSBAR; i<CS_AIRACCEL; i++)
@@ -1218,9 +1193,9 @@ void SCR_DumpStatusLayout_f (void)
 	bufcount = 0;
 
 	// write out the raw dump
-	Com_sprintf(statLine, sizeof(statLine), "\nRaw Dump\n--------\n");
-	Q_strncatz (buffer, statLine, sizeof(buffer));
-	bufcount += (int)strlen(statLine);
+	Com_sprintf(formatLine, sizeof(formatLine), "\nRaw Dump\n--------\n");
+	Q_strncatz (buffer, formatLine, sizeof(buffer));
+	bufcount += (int)strlen(formatLine);
 	fwrite(&buffer, 1, bufcount, f);
 	buffer[0] = 0;
 	bufcount = 0;
@@ -1237,10 +1212,9 @@ void SCR_DumpStatusLayout_f (void)
 	}
 
 	// write out the stat values for debugging
-	Com_sprintf(statLine, sizeof(statLine), "\nStat Values\n-----------\n");
-	Q_strncatz (buffer, statLine, sizeof(buffer));
-	bufcount += (int)strlen(statLine);
-
+	Com_sprintf(formatLine, sizeof(formatLine), "\nStat Values\n-----------\n");
+	Q_strncatz (buffer, formatLine, sizeof(buffer));
+	bufcount += (int)strlen(formatLine);
 	for (i=0; i<MAX_STATS; i++)
 	{
 		Com_sprintf(statLine, sizeof(statLine), "%i: %i\n", i, cl.frame.playerstate.stats[i]);
@@ -1257,6 +1231,34 @@ void SCR_DumpStatusLayout_f (void)
 	buffer[0] = 0;
 	bufcount = 0;
 
+	// write out CS_GENERAL for stat_string tokens
+	Com_sprintf(formatLine, sizeof(formatLine), "\nGeneral Configstrings\n---------------------\n");
+	Q_strncatz (buffer, formatLine, sizeof(buffer));
+	bufcount += (int)strlen(formatLine);
+	for (i = cs_general; i < (cs_general + MAX_GENERAL); i++)
+	{
+	/*	memset(rawLine, 0, sizeof(rawLine));
+		for (j=0; j<MAX_QPATH; j++) {
+			rawLine[j] = cl.configstrings[i][j];
+			if (rawLine[j] == '\0')	rawLine[j] = ' ';
+			if (rawLine[j] == '\t')	rawLine[j] = ' ';
+		}
+		rawLine[MAX_QPATH] = ' ';
+		Com_sprintf(formatLine, sizeof(formatLine), "%i: %s\n", i, rawLine);*/
+		Com_sprintf(formatLine, sizeof(formatLine), "%i: %s\n", i, cl.configstrings[i]);
+		// prevent overflow of buffer
+		if ( (bufcount + strlen(formatLine)) >= sizeof(buffer) ) {
+			fwrite(&buffer, 1, bufcount, f);
+			buffer[0] = 0;
+			bufcount = 0;
+		}
+		Q_strncatz (buffer, formatLine, sizeof(buffer));
+		bufcount += (int)strlen(formatLine);
+	}
+	fwrite(&buffer, 1, bufcount, f);
+	buffer[0] = 0;
+	bufcount = 0;
+
 	fclose (f);
 
 	Com_Printf ("Dumped statusbar layout to %s.\n", name);
@@ -2095,204 +2097,6 @@ void SCR_TileClear (void)
 }
 
 
-/*
-===============================================================
-
-HUD CODE
-
-===============================================================
-*/
-
-#define STAT_MINUS		10	// num frame for '-' stats digit
-char		*sb_nums[2][11] = 
-{
-	{"num_0", "num_1", "num_2", "num_3", "num_4", "num_5",
-	"num_6", "num_7", "num_8", "num_9", "num_minus"},
-	{"anum_0", "anum_1", "anum_2", "anum_3", "anum_4", "anum_5",
-	"anum_6", "anum_7", "anum_8", "anum_9", "anum_minus"}
-};
-
-/*
-================
-SizeHUDString
-
-Allow embedded \n in the string
-================
-*/
-void SizeHUDString (char *string, int *w, int *h, qboolean isStatusBar)
-{
-	int		lines, width, current;
-	float	(*scaleForScreen)(float in);
-
-	// Get our scaling function
-	if (isStatusBar)
-		scaleForScreen = SCR_ScaledHud;
-	else
-		scaleForScreen = SCR_ScaledScreen;
-
-	lines = 1;
-	width = 0;
-
-	current = 0;
-	while (*string)
-	{
-		if (*string == '\n')
-		{
-			lines++;
-			current = 0;
-		}
-		else
-		{
-			current++;
-			if (current > width)
-				width = current;
-		}
-		string++;
-	}
-
-//	*w = width * scaledHud(8);
-//	*h = lines * scaledHud(8);
-	*w = width * scaleForScreen(8);
-	*h = lines * scaleForScreen(8);
-}
-
-/*
-================
-CL_DrawLayoutString
-================
-*/
-void CL_DrawLayoutString (char *string, int x, int y, int centerwidth, int xor, qboolean isStatusBar)
-{
-	int		margin;
-	int		width, visibleWidth;
-	int		i, len;
-	char	line[1024];
-	float	(*scaleForScreen)(float in);
-
-	// Get our scaling function
-	if (isStatusBar)
-		scaleForScreen = SCR_ScaledHud;
-	else
-		scaleForScreen = SCR_ScaledScreen;
-
-	margin = x;
-
-//	len = strlen(string);
-
-	while (*string)
-	{
-		// scan out one line of text from the string
-		width = 0;
-		while (*string && *string != '\n')
-			line[width++] = *string++;
-
-		line[width] = 0;
-		visibleWidth = stringLen(line);
-
-		if (centerwidth)
-		//	x = margin + (centerwidth - width*scaledHud(8))/2;
-		//	x = margin + (centerwidth - width*scaleForScreen(8))/2;
-			x = margin + (centerwidth - visibleWidth*scaleForScreen(8))/2;
-		else
-			x = margin;
-
-
-		if (xor)
-		{	// Knightmare- text color hack
-		//	Com_sprintf (line, sizeof(line), S_COLOR_ALT"%s", line);
-			len = (int)strlen(line);
-			for (i=0; i<len; i++) {
-				line[i] ^= xor;
-			}
-		}
-		Hud_DrawString (x, y, line, 255, isStatusBar);
-
-		if (*string)
-		{
-			string++;	// skip the \n
-			x = margin;
-		//	y += scaledHud(8);
-			y += scaleForScreen(8);
-		}
-	}
-}
-
-
-/*
-==============
-SCR_DrawField
-==============
-*/
-void SCR_DrawField (int x, int y, int color, int width, int value, qboolean flash, qboolean isStatusBar)
-{
-	char		num[16], *ptr;
-	int			l, frame;
-	float		digitWidth, digitOffset, fieldScale;
-	float		flash_x, flashWidth;
-	float		(*scaleForScreen)(float in);
-	float		(*getScreenScale)(void);
-
-	if (width < 1)
-		return;
-
-	// Get our scaling functions
-	if (isStatusBar) {
-		scaleForScreen = SCR_ScaledHud;
-		getScreenScale = SCR_GetHudScale;
-	}
-	else {
-		scaleForScreen = SCR_ScaledScreen;
-		getScreenScale = SCR_GetScreenScale;
-	}
-
-	// draw number string
-	fieldScale = getScreenScale();
-	if (width > 5)
-		width = 5;
-
-	Com_sprintf (num, sizeof(num), "%i", value);
-	l = (int)strlen(num);
-	if (l > width)
-	{
-	//	if (scr_hudsqueezedigits->value) {
-		if (scr_hudsqueezedigits->integer) {
-			l = min(l, width+2);
-			fieldScale =  (1.0 - ((1.0 - (float)width/(float)l) * 0.5)) * getScreenScale();
-		}
-		else
-			l = width;
-	}
-	digitWidth = fieldScale*(float)CHAR_WIDTH;
-	digitOffset = width*scaleForScreen(CHAR_WIDTH) - l*digitWidth;
-//	x += 2 + scaledHud(CHAR_WIDTH)*(width - l);
-//	x += 2 + scaleForScreen(CHAR_WIDTH)*(width - l);
-	x += 2 + digitOffset;
-	flashWidth = l*digitWidth;
-	flash_x = x;
-
-	if (flash)
-		R_DrawStretchPic (flash_x, y, flashWidth, scaleForScreen(ICON_HEIGHT), "field_3", scr_hudalpha->value);
-
-	ptr = num;
-	while (*ptr && l)
-	{
-		if (*ptr == '-')
-			frame = STAT_MINUS;
-		else
-			frame = *ptr -'0';
-
-//		R_DrawScaledPic (x, y, HudScale(), scr_hudalpha->value,sb_nums[color][frame]);
-//		x += scaledHud(CHAR_WIDTH);
-//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, sb_nums[color][frame]);
-//		x += scaleForScreen(CHAR_WIDTH);
-		R_DrawStretchPic (x, y, digitWidth, scaleForScreen(ICON_HEIGHT), sb_nums[color][frame], scr_hudalpha->value);
-		x += digitWidth;
-		ptr++;
-		l--;
-	}
-}
-
-
 /*
 ===============
 SCR_TouchPics
@@ -2324,547 +2128,6 @@ void SCR_TouchPics (void)
 	}
 }
 
-/*
-================
-SCR_ExecuteLayoutString 
-
-================
-*/
-void SCR_ExecuteLayoutString (char *s, qboolean isStatusBar)
-{
-	int		x, y;
-	int		value, stat, width, index, cs_images, max_images;
-	char	*token;
-	clientinfo_t	*ci;
-	float			(*scaleForScreen)(float in);
-	float			(*getScreenScale)(void);
-	float			scrLeft, scrWidth;
-
-	if (cls.state != ca_active || !cl.refresh_prepped)
-		return;
-
-	if (!s[0])
-		return;
-
-	// Knightmare- hack for connected to server using old protocol
-	// Changed config strings require different parsing
-	if ( LegacyProtocol() ) {
-		cs_images = OLD_CS_IMAGES;
-		max_images = OLD_MAX_IMAGES;
-	}
-	else {
-		cs_images = CS_IMAGES;
-		max_images = MAX_IMAGES;
-	}
-
-	// Get our scaling functions
-	if (isStatusBar) {
-		scaleForScreen = SCR_ScaledHud;
-		getScreenScale = SCR_GetHudScale;
-	}
-	else {
-		scaleForScreen = SCR_ScaledScreen;
-		getScreenScale = SCR_GetScreenScale;
-	}
-
-	SCR_InitHudScale ();
-	x = 0;
-	y = 0;
-	width = 3;
-
-	scrLeft = 0;
-	scrWidth = SCREEN_WIDTH;
-	SCR_AdjustFrom640 (&scrLeft, NULL, &scrWidth, NULL, ALIGN_STRETCH);
-
-	while (s)
-	{
-		token = COM_Parse (&s);
-		if (!strcmp(token, "xl"))
-		{
-			token = COM_Parse (&s);
-		//	x = scaleForScreen(atoi(token));
-			x = (int)scrLeft + scaleForScreen(atoi(token));
-			continue;
-		}
-		if (!strcmp(token, "xr"))
-		{
-			token = COM_Parse (&s);
-		//	x = viddef.width + scaleForScreen(atoi(token));
-			x = (int)(scrLeft + scrWidth) + scaleForScreen(atoi(token));
-			continue;
-		}
-		if (!strcmp(token, "xv"))
-		{
-			token = COM_Parse (&s);
-			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
-			continue;
-		}
-		if (!strcmp(token, "yt"))
-		{
-			token = COM_Parse (&s);
-			y = scaleForScreen(atoi(token));
-			continue;
-		}
-		if (!strcmp(token, "yb"))
-		{
-			token = COM_Parse (&s);
-			y = viddef.height + scaleForScreen(atoi(token));
-			continue;
-		}
-		if (!strcmp(token, "yv"))
-		{
-			token = COM_Parse (&s);
-			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
-			continue;
-		}
-
-		if (!strcmp(token, "pic"))
-		{	// draw a pic from a stat number
-			token = COM_Parse (&s);
-		//	value = cl.frame.playerstate.stats[atoi(token)];
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
-				Com_Error (ERR_DROP, "Bad pic stat index");
-			value = cl.frame.playerstate.stats[stat];
-			if (value >= max_images) // Knightmare- don't bomb out
-			//	Com_Error (ERR_DROP, "Pic >= MAX_IMAGES");
-			{
-				Com_Printf (S_COLOR_YELLOW"WARNING: Pic >= MAX_IMAGES\n");
-				value = max_images-1;
-			}
-			if (cl.configstrings[cs_images+value])
-			{
-				R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, cl.configstrings[cs_images+value]);
-			}
-			continue;
-		}
-
-		if (!strcmp(token, "client"))
-		{	// draw a deathmatch client block
-			int		score, ping, time;
-
-			token = COM_Parse (&s);
-			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
-			token = COM_Parse (&s);
-			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
-
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (value >= MAX_CLIENTS || value < 0)
-				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
-			ci = &cl.clientinfo[value];
-
-			token = COM_Parse (&s);
-			score = atoi(token);
-
-			token = COM_Parse (&s);
-			ping = atoi(token);
-
-			token = COM_Parse (&s);
-			time = atoi(token);
-
-			Hud_DrawStringAlt (x+scaleForScreen(32), y, va(S_COLOR_ALT"%s", ci->name), 255, isStatusBar);
-			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(8),  "Score: ", 255, isStatusBar);
-			Hud_DrawStringAlt (x+scaleForScreen(32+7*8), y+scaleForScreen(8),  va(S_COLOR_ALT"%i", score), 255, isStatusBar);
-			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(16), va("Ping:  %i", ping), 255, isStatusBar);
-			Hud_DrawString (x+scaleForScreen(32), y+scaleForScreen(24), va("Time:  %i", time), 255, isStatusBar);
-
-			if (!ci->icon)
-				ci = &cl.baseclientinfo;
-			R_DrawScaledPic(x, y, getScreenScale(), scr_hudalpha->value,  ci->iconname);
-			continue;
-		}
-
-		if (!strcmp(token, "ctf"))
-		{	// draw a ctf client block
-			int		score, ping;
-			char	block[80];
-
-			token = COM_Parse (&s);
-			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
-			token = COM_Parse (&s);
-			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
-
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (value >= MAX_CLIENTS || value < 0)
-				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
-			ci = &cl.clientinfo[value];
-
-			token = COM_Parse (&s);
-			score = atoi(token);
-
-			token = COM_Parse (&s);
-			ping = atoi(token);
-			if (ping > 999)
-				ping = 999;
-
-			sprintf(block, "%3d %3d %-12.12s", score, ping, ci->name);
-
-			if (value == cl.playernum)
-				Hud_DrawStringAlt (x, y, block, 255, isStatusBar);
-			else
-				Hud_DrawString (x, y, block, 255, isStatusBar);
-			continue;
-		}
-		
-		if (!strcmp(token, "3tctf")) // Knightmare- 3Team CTF block
-		{	// draw a 3Team CTF client block
-			int		score, ping;
-			char	block[80];
-
-			token = COM_Parse (&s);
-			x = viddef.width/2 - scaleForScreen(160) + scaleForScreen(atoi(token));
-			token = COM_Parse (&s);
-			y = viddef.height/2 - scaleForScreen(120) + scaleForScreen(atoi(token));
-
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (value >= MAX_CLIENTS || value < 0)
-				Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
-			ci = &cl.clientinfo[value];
-
-			token = COM_Parse (&s);
-			score = atoi(token);
-
-			token = COM_Parse (&s);
-			ping = atoi(token);
-			if (ping > 999)
-				ping = 999;
-			// double spaced before player name for 2 flag icons
-			sprintf(block, "%3d %3d  %-12.12s", score, ping, ci->name);
-
-			if (value == cl.playernum)
-				Hud_DrawStringAlt (x, y, block, 255, isStatusBar);
-			else
-				Hud_DrawString (x, y, block, 255, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "picn"))
-		{	// draw a pic from a name
-			token = COM_Parse (&s);
-			R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, token);
-			continue;
-		}
-
-		if (!strcmp(token, "num"))
-		{	// draw a number
-			token = COM_Parse (&s);
-			width = atoi(token);
-			token = COM_Parse (&s);
-		//	value = cl.frame.playerstate.stats[atoi(token)];
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
-				Com_Error (ERR_DROP, "Bad num stat index");
-			value = cl.frame.playerstate.stats[stat];
-			SCR_DrawField (x, y, 0, width, value, false, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "hnum"))
-		{	// health number
-			int		color;
-
-			width = 3;
-			value = cl.frame.playerstate.stats[STAT_HEALTH];
-			if (value > 25)
-				color = 0;	// green
-			else if (value > 0)
-				color = (cl.frame.serverframe>>2) & 1;		// flash
-			else
-				color = 1;
-
-		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 1)
-		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
-
-			SCR_DrawField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 1), isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "anum"))
-		{	// ammo number
-			int		color;
-
-			width = 3;
-			value = cl.frame.playerstate.stats[STAT_AMMO];
-			if (value > 5)
-				color = 0;	// green
-			else if (value >= 0)
-				color = (cl.frame.serverframe>>2) & 1;		// flash
-			else
-				continue;	// negative number = don't show
-
-		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 4)
-		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
-
-			SCR_DrawField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 4), isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "rnum"))
-		{	// armor number
-			int		color;
-
-			width = 3;
-			value = cl.frame.playerstate.stats[STAT_ARMOR];
-			if (value < 1)
-				continue;
-
-			color = 0;	// green
-
-		//	if (cl.frame.playerstate.stats[STAT_FLASHES] & 2)
-		//		R_DrawScaledPic (x, y, getScreenScale(), scr_hudalpha->value, "field_3");
-
-			SCR_DrawField (x, y, color, width, value, (cl.frame.playerstate.stats[STAT_FLASHES] & 2), isStatusBar);
-			continue;
-		}
-
-
-		if (!strcmp(token, "stat_string"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)	// MAX_CONFIGSTRINGS
-				Com_Error (ERR_DROP, "Bad stat_string stat index");
-			index = cl.frame.playerstate.stats[stat];
-			if (index < 0 || index >= MAX_CONFIGSTRINGS)
-				Com_Error (ERR_DROP, "Bad stat_string configstring index");
-			Hud_DrawString (x, y, cl.configstrings[index], 255, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "cstring"))
-		{
-			token = COM_Parse (&s);
-			CL_DrawLayoutString (token, x, y, scaleForScreen(320), 0, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "string"))
-		{
-			token = COM_Parse (&s);
-			Hud_DrawString (x, y, token, 255, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "cstring2"))
-		{
-			token = COM_Parse (&s);
-			CL_DrawLayoutString (token, x, y, scaleForScreen(320), 0x80, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "string2"))
-		{
-			token = COM_Parse (&s);
-			Hud_DrawStringAlt (x, y, token, 255, isStatusBar);
-			continue;
-		}
-
-		if (!strcmp(token, "if"))
-		{	// draw a number
-			token = COM_Parse (&s);
-		//	value = cl.frame.playerstate.stats[atoi(token)];
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)	// check bounds on stat
-				Com_Error (ERR_DROP, "Bad if stat index");
-			value = cl.frame.playerstate.stats[stat];
-			if (!value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}
-			}
-
-			continue;
-		}
-
-		// ifeq <stat> <value>
-		// ifbit <stat> <value>
-
-		// Knightmare- added more commands
-		if (!strcmp(token, "ifeq"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifeq stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] != value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifneq"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifneq stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] == value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifgt"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifgt stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] <= value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifge"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifge stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] < value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "iflt"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad iflt stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] >= value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifle"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifle stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (cl.frame.playerstate.stats[stat] > value)
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifbit"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifbit stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (value < 1 || value > 16)
-				Com_Error (ERR_DROP, "Bad ifbit bit value");
-			if ( !(cl.frame.playerstate.stats[stat] & (1<<(value-1))) )
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-
-		if (!strcmp(token, "ifnbit"))
-		{
-			token = COM_Parse (&s);
-			stat = atoi(token);
-			if (stat < 0 || stat >= MAX_STATS)
-				Com_Error (ERR_DROP, "Bad ifnbit stat index");
-			token = COM_Parse (&s);
-			value = atoi(token);
-			if (value < 1 || value > 16)
-				Com_Error (ERR_DROP, "Bad ifnbit bit value");
-			if ( cl.frame.playerstate.stats[stat] & (1<<(value-1)) )
-			{	// skip to endif
-				while (s && strcmp(token, "endif") )
-				{
-					token = COM_Parse (&s);
-				}			
-			}
-		}
-		// end Knightmare
-	}
-}
-
-
-/*
-================
-SCR_DrawStats
-
-The status bar is a small layout program that
-is based on the stats array
-================
-*/
-void SCR_DrawStats (void)
-{
-	SCR_ExecuteLayoutString (cl.configstrings[CS_STATUSBAR], true);
-}
-
-
-/*
-================
-SCR_DrawLayout
-
-================
-*/
-#define	STAT_LAYOUTS		13
-
-void SCR_DrawLayout (void)
-{
-	qboolean isStatusBar = false;
-
-	if (!cl.frame.playerstate.stats[STAT_LAYOUTS])
-		return;
-
-	// Special hack for visor HUD addition in Zaero
-	if ( strstr(cl.layout, "\"Tracking ") )
-		isStatusBar = true;
-
-	SCR_ExecuteLayoutString (cl.layout, isStatusBar);
-}
-
 //=======================================================
 
 void DrawDemoMessage (void)
@@ -3009,9 +2272,9 @@ void SCR_UpdateScreen (void)
 
 			if (!scr_hidehud)
 			{
-				SCR_DrawStats ();
+				CL_DrawStatus ();
 				if (cl.frame.playerstate.stats[STAT_LAYOUTS] & 1)
-					SCR_DrawLayout ();
+					CL_DrawLayout ();
 				if (cl.frame.playerstate.stats[STAT_LAYOUTS] & 2)
 					CL_DrawInventory ();
 			}
diff --git a/client/client.h b/client/client.h
index 1a1c6e2..ee84db1 100644
--- a/client/client.h
+++ b/client/client.h
@@ -1145,11 +1145,9 @@ void UI_AddToServerList (netadr_t adr, char *info);
 void M_Menu_Main_f (void);
 
 //
-// cl_inv.c
+// cl_hud.c
 //
 void CL_ParseInventory (void);
-void CL_KeyInventory (int key);
-void CL_DrawInventory (void);
 
 //
 // cl_pred.c
diff --git a/client/screen.h b/client/screen.h
index 249f9bf..f25abde 100644
--- a/client/screen.h
+++ b/client/screen.h
@@ -57,36 +57,11 @@ SCALETYPE_HUD,
 SCALETYPE_MENU
 } textscaletype_t;
 
+#define	STAT_MINUS		10	// num frame for '-' stats digit
+#define CHAR_WIDTH		16
 
-void	SCR_Init (void);
-
-void	SCR_UpdateScreen (void);
-
-void	SCR_SizeUp (void);
-void	SCR_SizeDown (void);
-void	SCR_CenterPrint (char *str);
-void	SCR_BeginLoadingPlaque (void);
-void	SCR_EndLoadingPlaque (void);
-
-void	SCR_DebugGraph (float value, int color);
-
-void	SCR_TouchPics (void);
-
-void	SCR_RunLetterbox (void);
-void	SCR_RunConsole (void);
-
-void	SCR_InitScreenScale (void);
-void	SCR_AdjustFrom640 (float *x, float *y, float *w, float *h, scralign_t align);
-float	SCR_ScaledScreen (float param);
-float	SCR_GetScreenScale (void);
-
-void	SCR_AdjustFrom640 (float *x, float *y, float *w, float *h, scralign_t align);
-void	SCR_DrawFill (float x, float y, float width, float height, scralign_t align, int red, int green, int blue, int alpha);
-void	SCR_DrawPic (float x, float y, float width, float height, scralign_t align, char *pic, float alpha);
-void	SCR_DrawChar (float x, float y, int size, scralign_t align, int num, int red, int green, int blue, int alpha, qboolean italic, qboolean last);
-void	SCR_DrawString (float x, float y, int size, scralign_t align, const char *string, int alpha);
-void	SCR_DrawCrosshair (void);
 
+extern	char		*sb_nums[2][11];
 
 extern	float		scr_con_current;
 extern	float		scr_conlines;		// lines of console to display
@@ -123,13 +98,51 @@ extern	int			crosshair_width, crosshair_height;
 
 #define HUD_FONT_SIZE	8.0
 
+//
+// cl_screen.c
+//
+void	SCR_Init (void);
+void	SCR_UpdateScreen (void);
+
+void	SCR_SizeUp (void);
+void	SCR_SizeDown (void);
+void	SCR_CenterPrint (char *str);
+void	SCR_BeginLoadingPlaque (void);
+void	SCR_EndLoadingPlaque (void);
+
+void	SCR_DebugGraph (float value, int color);
+
+void	SCR_TouchPics (void);
+
+void	SCR_RunLetterbox (void);
+void	SCR_RunConsole (void);
+
+void	SCR_InitScreenScale (void);
+void	SCR_AdjustFrom640 (float *x, float *y, float *w, float *h, scralign_t align);
+float	SCR_ScaledScreen (float param);
+float	SCR_GetScreenScale (void);
+
+void	SCR_AdjustFrom640 (float *x, float *y, float *w, float *h, scralign_t align);
+void	SCR_DrawFill (float x, float y, float width, float height, scralign_t align, int red, int green, int blue, int alpha);
+void	SCR_DrawPic (float x, float y, float width, float height, scralign_t align, char *pic, float alpha);
+void	SCR_DrawChar (float x, float y, int size, scralign_t align, int num, int red, int green, int blue, int alpha, qboolean italic, qboolean last);
+void	SCR_DrawString (float x, float y, int size, scralign_t align, const char *string, int alpha);
+void	SCR_DrawCrosshair (void);
 
 //
-// scr_cin.c
+// cl_hud.c
 //
-void SCR_PlayCinematic (char *name);
+void	Hud_DrawString (int x, int y, const char *string, int alpha, qboolean isStatusBar);
+void	Hud_DrawStringAlt (int x, int y, const char *string, int alpha, qboolean isStatusBar);
+void	CL_DrawStatus (void);
+void	CL_DrawLayout (void);
+void	CL_DrawInventory (void);
+
+//
+// cl_cin.c
+//
+void	SCR_PlayCinematic (char *name);
 qboolean SCR_DrawCinematic (void);
-void SCR_RunCinematic (void);
-void SCR_StopCinematic (void);
-void SCR_FinishCinematic (void);
-
+void	SCR_RunCinematic (void);
+void	SCR_StopCinematic (void);
+void	SCR_FinishCinematic (void);
diff --git a/projects/VC6/kmquake2.dsp b/projects/VC6/kmquake2.dsp
index 44b2e04..16756c2 100644
--- a/projects/VC6/kmquake2.dsp
+++ b/projects/VC6/kmquake2.dsp
@@ -157,11 +157,11 @@ SOURCE=..\..\client\cl_http.c
 # End Source File
 # Begin Source File
 
-SOURCE=..\..\client\cl_input.c
+SOURCE=..\..\client\cl_hud.c
 # End Source File
 # Begin Source File
 
-SOURCE=..\..\client\cl_inv.c
+SOURCE=..\..\client\cl_input.c
 # End Source File
 # Begin Source File
 
diff --git a/projects/VS2005/kmquake2_2005.vcproj b/projects/VS2005/kmquake2_2005.vcproj
index ed5e3c5..cb89b9f 100644
--- a/projects/VS2005/kmquake2_2005.vcproj
+++ b/projects/VS2005/kmquake2_2005.vcproj
@@ -284,11 +284,11 @@
 					>
 				</File>
 				<File
-					RelativePath="..\..\client\cl_input.c"
+					RelativePath="..\..\client\cl_hud.c"
 					>
 				</File>
 				<File
-					RelativePath="..\..\client\cl_inv.c"
+					RelativePath="..\..\client\cl_input.c"
 					>
 				</File>
 				<File
diff --git a/projects/VS2008/kmquake2_2008.vcproj b/projects/VS2008/kmquake2_2008.vcproj
index 3a97819..6efeee6 100644
--- a/projects/VS2008/kmquake2_2008.vcproj
+++ b/projects/VS2008/kmquake2_2008.vcproj
@@ -492,11 +492,11 @@
 					>
 				</File>
 				<File
-					RelativePath="..\..\client\cl_input.c"
+					RelativePath="..\..\client\cl_hud.c"
 					>
 				</File>
 				<File
-					RelativePath="..\..\client\cl_inv.c"
+					RelativePath="..\..\client\cl_input.c"
 					>
 				</File>
 				<File
@@ -882,11 +882,11 @@
 			Filter="h;hpp;hxx;hm;inl;fi;fd"
 			>
 			<File
-				RelativePath="..\..\client\anorms.h"
+				RelativePath="..\..\renderer\anorms.h"
 				>
 			</File>
 			<File
-				RelativePath="..\..\renderer\anorms.h"
+				RelativePath="..\..\client\anorms.h"
 				>
 			</File>
 			<File