From 6e81e12456f11f8e8fd7de9650dbe65e29a140ac Mon Sep 17 00:00:00 2001
From: Knightmare66 <knightmare66@yahoo.com>
Date: Fri, 29 Jan 2021 00:29:13 -0500
Subject: [PATCH] Rewrote Q_strncpyz() and Q_strncatz() to not be based on
 strncpy() and to return size copied. Fixed g_ctf.c->CTFSay_Team_Location()
 not supporting green team in 3TCTF mode.

---
 game/g_ctf.c       | 110 ++++++++++++++++++++++++++++-----------------
 game/g_func_decs.h |   4 +-
 game/q_shared.c    |  58 +++++++++++++++++++-----
 game/q_shared.h    |   4 +-
 4 files changed, 120 insertions(+), 56 deletions(-)

diff --git a/game/g_ctf.c b/game/g_ctf.c
index 42fa0f2..c3756f3 100644
--- a/game/g_ctf.c
+++ b/game/g_ctf.c
@@ -1563,7 +1563,8 @@ void CTFFlagSetup (edict_t *ent)
 			ent->item->world_model = "models/ctf/flags/flag1.md2";
 		if (strcmp(ent->classname, "item_flag_team2") == 0)
 			ent->item->world_model = "models/ctf/flags/flag2.md2";
-	} else {
+	}
+	else {
 		if (strcmp(ent->classname, "item_flag_team1") == 0)
 			ent->item->world_model = "players/male/flag1.md2";
 		if (strcmp(ent->classname, "item_flag_team2") == 0)
@@ -3683,17 +3684,17 @@ struct {
 
 /*static*/ void CTFSay_Team_Location (edict_t *who, char *buf, size_t bufSize)
 {
-	edict_t *what = NULL;
-	edict_t *hot = NULL;
-	float hotdist = 999999, newdist;
-	vec3_t v;
-	int hotindex = 999;
-	int i;
-	gitem_t *item;
-	int nearteam = -1;
-	edict_t *flag1, *flag2;
-	qboolean hotsee = false;
-	qboolean cansee;
+	edict_t		*what = NULL;
+	edict_t		*hot = NULL;
+	float		hotdist = 999999, newdist, newdist2;
+	vec3_t		v;
+	int			hotindex = 999;
+	int			i;
+	gitem_t		*item;
+	int			nearteam = -1;
+	edict_t		*flag1, *flag2, *flag3;
+	qboolean	hotsee = false;
+	qboolean	cansee;
 
 	while ((what = loc_findradius(what, who->s.origin, 1024)) != NULL) {
 		// find what in loc_classnames
@@ -3743,16 +3744,40 @@ struct {
 			continue;
 		// if we are here, there is more than one, find out if hot
 		// is closer to red flag or blue flag
-		if ((flag1 = G_Find(NULL, FOFS(classname), "item_flag_team1")) != NULL &&
-			(flag2 = G_Find(NULL, FOFS(classname), "item_flag_team2")) != NULL) {
-			VectorSubtract(hot->s.origin, flag1->s.origin, v);
-			hotdist = VectorLength(v);
-			VectorSubtract(hot->s.origin, flag2->s.origin, v);
-			newdist = VectorLength(v);
-			if (hotdist < newdist)
-				nearteam = CTF_TEAM1;
-			else if (hotdist > newdist)
-				nearteam = CTF_TEAM2;
+		if (ttctf->value)
+		{
+			if ((flag1 = G_Find(NULL, FOFS(classname), "item_flag_team1")) != NULL &&
+				(flag2 = G_Find(NULL, FOFS(classname), "item_flag_team2")) != NULL &&
+				(flag3 = G_Find(NULL, FOFS(classname), "item_flag_team3")) != NULL)
+			{
+				VectorSubtract(hot->s.origin, flag1->s.origin, v);
+				hotdist = VectorLength(v);
+				VectorSubtract(hot->s.origin, flag2->s.origin, v);
+				newdist = VectorLength(v);
+				VectorSubtract(hot->s.origin, flag3->s.origin, v);
+				newdist2 = VectorLength(v);
+				if ( (hotdist < newdist) && (hotdist < newdist2) )
+					nearteam = CTF_TEAM1;
+				else if ( (hotdist > newdist) && (newdist2 > newdist) )
+					nearteam = CTF_TEAM2;
+				else if ( (newdist2 < hotdist) && (newdist2 < newdist) )
+					nearteam = CTF_TEAM3;
+			}
+		}
+		else
+		{
+			if ((flag1 = G_Find(NULL, FOFS(classname), "item_flag_team1")) != NULL &&
+				(flag2 = G_Find(NULL, FOFS(classname), "item_flag_team2")) != NULL)
+			{
+				VectorSubtract(hot->s.origin, flag1->s.origin, v);
+				hotdist = VectorLength(v);
+				VectorSubtract(hot->s.origin, flag2->s.origin, v);
+				newdist = VectorLength(v);
+				if (hotdist < newdist)
+					nearteam = CTF_TEAM1;
+				else if (hotdist > newdist)
+					nearteam = CTF_TEAM2;
+			}
 		}
 		break;
 	}
@@ -3789,6 +3814,9 @@ struct {
 	else if (nearteam == CTF_TEAM2)
 	//	strncat(buf, "the blue ");
 		Q_strncatz(buf, bufSize, "the blue ");
+	else if (nearteam == CTF_TEAM3)
+	//	strncat(buf, "the blue ");
+		Q_strncatz(buf, bufSize, "the green ");
 	else
 	//	strncat(buf, "the ");
 		Q_strncatz(buf, bufSize, "the ");
@@ -3940,7 +3968,7 @@ void CTFSay_Team (edict_t *who, char *msg)
 		msg++;
 	}
 
-	for (p = outmsg; *msg && (p - outmsg) < sizeof(outmsg) - 2; msg++)
+	for (p = outmsg; *msg && (p - outmsg) < sizeof(outmsg) - 1; msg++)	// was -2
 	{
 		if (*msg == '%')
 		{
@@ -3949,9 +3977,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 'l' :
 				case 'L' :
 					CTFSay_Team_Location(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
@@ -3959,9 +3987,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 'a' :
 				case 'A' :
 					CTFSay_Team_Armor(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
@@ -3969,9 +3997,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 'h' :
 				case 'H' :
 					CTFSay_Team_Health(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
@@ -3979,9 +4007,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 't' :
 				case 'T' :
 					CTFSay_Team_Tech(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
@@ -3989,9 +4017,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 'w' :
 				case 'W' :
 					CTFSay_Team_Weapon(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
@@ -4000,9 +4028,9 @@ void CTFSay_Team (edict_t *who, char *msg)
 				case 'n' :
 				case 'N' :
 					CTFSay_Team_Sight(who, buf, sizeof(buf));
-					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 2) {
-						strcpy(p, buf);
-					//	Q_strncpyz(p, outmsgSize-2, buf);
+					if (strlen(buf) + (p - outmsg) < sizeof(outmsg) - 1) {	// was -2
+					//	strncpy(p, buf);
+						Q_strncpyz(p, sizeof(outmsg) - (p - outmsg) - 1, buf);
 						p += strlen(buf);
 					//	outmsgSize -= strlen(buf);
 					}
diff --git a/game/g_func_decs.h b/game/g_func_decs.h
index 9a32dc7..4828989 100644
--- a/game/g_func_decs.h
+++ b/game/g_func_decs.h
@@ -7,8 +7,8 @@ extern void Com_sprintf ( char * dest , size_t size , char * fmt , ... ) ;
 extern char * Q_strupr ( char * string ) ;
 extern char * Q_strlwr ( char * string ) ;
 extern void Q_snprintfz ( char * dst , size_t dstSize , const char * fmt , ... ) ;
-extern void Q_strncatz ( char * dst , size_t dstSize , const char * src ) ;
-extern void Q_strncpyz ( char * dst , size_t dstSize , const char * src ) ;
+extern size_t Q_strncatz ( char * dst , size_t dstSize , const char * src ) ;
+extern size_t Q_strncpyz ( char * dst , size_t dstSize , const char * src ) ;
 extern int Q_strcasecmp ( char * s1 , char * s2 ) ;
 extern int Q_strncasecmp ( char * s1 , char * s2 , size_t n ) ;
 extern int Q_SortStrcmp ( const char * * arg1 , const char * * arg2 ) ;
diff --git a/game/q_shared.c b/game/q_shared.c
index 839b64d..7aed45f 100644
--- a/game/q_shared.c
+++ b/game/q_shared.c
@@ -1998,26 +1998,40 @@ Q_strncpyz
 Safe strncpy that ensures a trailing zero
 =================
 */
-void Q_strncpyz (char *dst, size_t dstSize, const char *src)
+size_t Q_strncpyz (char *dst, size_t dstSize, const char *src)
 {
+	char		*d = dst;
+	const char	*s = src;
+	size_t		decSize = dstSize;
+
 	if (!dst) {
 	//	Com_Error (ERR_FATAL, "Q_strncpyz: NULL dst");
 	//	Com_Printf ("Q_strncpyz: NULL dst\n");
-		return;
+		return 0;
 	}
 	if (!src) {
 	//	Com_Error (ERR_FATAL, "Q_strncpyz: NULL src");
 	//	Com_Printf ("Q_strncpyz: NULL src\n");
-		return;
+		return 0;
 	}
 	if (dstSize < 1) {
 	//	Com_Error (ERR_FATAL, "Q_strncpyz: dstSize < 1");
 	//	Com_Printf ("Q_strncpyz: dstSize < 1\n");
-		return;
+		return 0;
 	}
 
-	strncpy(dst, src, dstSize-1);
+//	strncpy(dst, src, dstSize-1);
+//	dst[dstSize-1] = 0;
+
+	while (--decSize && *s)
+		*d++ = *s++;
+	*d = 0;
 	dst[dstSize-1] = 0;
+
+	if (decSize == 0)	// Unsufficent room in dst, return count + length of remaining src
+		return (s - src - 1 + strlen(s));
+	else
+		return (s - src - 1);	// returned count excludes NULL terminator
 }
 
 
@@ -2028,25 +2042,30 @@ Q_strncatz
 Safe strncat that ensures a trailing zero
 =================
 */
-void Q_strncatz (char *dst, size_t dstSize, const char *src)
+size_t Q_strncatz (char *dst, size_t dstSize, const char *src)
 {
+	char		*d = dst;
+	const char	*s = src;
+	size_t		decSize = dstSize;
+	size_t		dLen;
+
 	if (!dst) {
 	//	Com_Error (ERR_FATAL, "Q_strncatz: NULL dst");
 	//	Com_Printf ("Q_strncatz: NULL dst\n");
-		return;
+		return 0;
 	}
 	if (!src) {
 	//	Com_Error (ERR_FATAL, "Q_strncatz: NULL src");
 	//	Com_Printf ("Q_strncatz: NULL src\n");
-		return;
+		return 0;
 	}
 	if (dstSize < 1) {
 	//	Com_Error (ERR_FATAL, "Q_strncatz: dstSize < 1");
 	//	Com_Printf ("Q_strncatz: dstSize < 1\n");
-		return;
+		return 0;
 	}
 
-	while (--dstSize && *dst)
+/*	while (--dstSize && *dst)
 		dst++;
 
 	if (dstSize > 0){
@@ -2054,7 +2073,24 @@ void Q_strncatz (char *dst, size_t dstSize, const char *src)
 			*dst++ = *src++;
 
 		*dst = 0;
+	}*/
+
+	while (--decSize && *d)
+		d++;
+	dLen = d - dst;
+
+	if (decSize == 0)
+		return (dLen + strlen(s));
+
+	if (decSize > 0) {
+		while (--decSize && *s)
+			*d++ = *s++;
+
+		*d = 0;
 	}
+	dst[dstSize-1] = 0;
+
+	return (dLen + (s - src));	// returned count excludes NULL terminator
 }
 
 
@@ -2067,7 +2103,7 @@ Safe snprintf that ensures a trailing zero
 */
 void Q_snprintfz (char *dst, size_t dstSize, const char *fmt, ...)
 {
-	va_list	argPtr;
+	va_list		argPtr;
 
 	if (!dst) {
 	//	Com_Error(ERR_FATAL, "Q_snprintfz: NULL dst");
diff --git a/game/q_shared.h b/game/q_shared.h
index d42548c..cbc44c0 100644
--- a/game/q_shared.h
+++ b/game/q_shared.h
@@ -467,8 +467,8 @@ int Q_stricmp (char *s1, char *s2);
 int Q_strcasecmp (char *s1, char *s2);
 int Q_strncasecmp (char *s1, char *s2, size_t n);
 
-void Q_strncpyz (char *dst, size_t dstSize, const char *src);
-void Q_strncatz (char *dst, size_t dstSize, const char *src);
+size_t Q_strncpyz (char *dst, size_t dstSize, const char *src);
+size_t Q_strncatz (char *dst, size_t dstSize, const char *src);
 void Q_snprintfz (char *dst, size_t dstSize, const char *fmt, ...);
 char *Q_strlwr (char *string);
 char *Q_strupr (char *string);