1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // string.c
22 //
23 
24 #include "shared.h"
25 
26 /*
27 =============================================================================
28 
29 	COLOR STRING HANDLING
30 
31 =============================================================================
32 */
33 
34 vec4_t	Q_colorBlack	= { 0, 0, 0, 1 };
35 vec4_t	Q_colorRed		= { 1, 0, 0, 1 };
36 vec4_t	Q_colorGreen	= { 0, 1, 0, 1 };
37 vec4_t	Q_colorYellow	= { 1, 1, 0, 1 };
38 vec4_t	Q_colorBlue		= { 0, 0, 1, 1 };
39 vec4_t	Q_colorCyan		= { 0, 1, 1, 1 };
40 vec4_t	Q_colorMagenta	= { 1, 0, 1, 1 };
41 vec4_t	Q_colorWhite	= { 1, 1, 1, 1 };
42 
43 vec4_t	Q_colorLtGrey	= { 0.75, 0.75, 0.75, 1 };
44 vec4_t	Q_colorMdGrey	= { 0.5, 0.5, 0.5, 1 };
45 vec4_t	Q_colorDkGrey	= { 0.25, 0.25, 0.25, 1 };
46 
47 vec4_t	Q_strColorTable[10] = {
48 	{ 0.0f, 0.0f, 0.0f, 1.0f },
49 	{ 1.0f, 0.0f, 0.0f, 1.0f },
50 	{ 0.0f, 1.0f, 0.0f, 1.0f },
51 	{ 1.0f, 1.0f, 0.0f, 1.0f },
52 	{ 0.0f, 0.0f, 1.0f, 1.0f },
53 	{ 0.0f, 1.0f, 1.0f, 1.0f },
54 	{ 1.0f, 0.0f, 1.0f, 1.0f },
55 	{ 1.0f, 1.0f, 1.0f, 1.0f },
56 
57 	{ 0.75f, 0.75f, 0.75f, 1.0f },
58 	{ 0.25f, 0.25f, 0.25f, 1.0f }
59 };
60 
61 /*
62 ===============
63 Q_ColorCharCount
64 ===============
65 */
Q_IsColorString(const char * p)66 qBool Q_IsColorString (const char *p)
67 {
68 	if (!*p || (*p & 127) != COLOR_ESCAPE)
69 		return qFalse;
70 
71 	switch (p[1] & 127) {
72 	case '0':	case '1':	case '2':	case '3':	case '4':
73 	case '5':	case '6':	case '7':	case '8':	case '9':
74 	case 'i':	case 'I':	// S_STYLE_ITALIC
75 	case 'r':	case 'R':	// S_STYLE_RETURN
76 	case 's':	case 'S':	// S_STYLE_SHADOW
77 	case '^':				// COLOR_ESCAPE
78 		return qTrue;
79 	}
80 
81 	return qFalse;
82 }
83 
84 
85 /*
86 ===============
87 Q_ColorCharCount
88 ===============
89 */
Q_ColorCharCount(const char * s,int endPos)90 int Q_ColorCharCount (const char *s, int endPos)
91 {
92 	int			count;
93 	const char	*end;
94 
95 	end = s + endPos;
96 	for (count=0 ; *s && s<end ; s++) {
97 		if ((s[0] & 127) != COLOR_ESCAPE)
98 			continue;
99 
100 		switch (s[1] & 127) {
101 		case '0':	case '1':	case '2':	case '3':	case '4':
102 		case '5':	case '6':	case '7':	case '8':	case '9':
103 		case 'i':	case 'I':
104 		case 'r':	case 'R':
105 		case 's':	case 'S':
106 			count += 2;
107 			break;
108 		case '^':
109 			count++;
110 			break;
111 		}
112 	}
113 
114 	return endPos - count;
115 }
116 
117 
118 /*
119 ===============
120 Q_ColorCharOffset
121 ===============
122 */
Q_ColorCharOffset(const char * s,int charCount)123 int Q_ColorCharOffset (const char *s, int charCount)
124 {
125 	const char	*start = s;
126 	qBool		skipNext = qFalse;
127 
128 	for ( ; *s && charCount ; s++) {
129 		if (skipNext)
130 			skipNext = qFalse;
131 		else if (Q_IsColorString (s)) {
132 			skipNext = qTrue;
133 		}
134 		else
135 			charCount--;
136 	}
137 
138 	return s - start;
139 }
140 
141 
142 /*
143 ===============
144 Q_ColorStrLastColor
145 ===============
146 */
Q_ColorStrLastColor(char * s,int byteOfs)147 int Q_ColorStrLastColor (char *s, int byteOfs)
148 {
149 	char	*end;
150 	int		lastClrIndex = Q_StrColorIndex (COLOR_WHITE);
151 
152 	end = s + (byteOfs - 1);	// don't check last byte
153 	for ( ; *s && s<end ; s++) {
154 		if ((s[0] & 127) != COLOR_ESCAPE)
155 			continue;
156 
157 		switch (s[1] & 127) {
158 		case '0':	case '1':	case '2':	case '3':	case '4':
159 		case '5':	case '6':	case '7':	case '8':	case '9':
160 			lastClrIndex = (s[1] & 127) - '0';
161 			break;
162 		case 'r':	case 'R':
163 			lastClrIndex = Q_StrColorIndex (COLOR_WHITE);
164 			break;
165 		default:
166 			continue;
167 		}
168 
169 		s++;
170 	}
171 
172 	return lastClrIndex;
173 }
174 
175 
176 /*
177 ===============
178 Q_ColorStrLastStyle
179 ===============
180 */
Q_ColorStrLastStyle(char * s,int byteOfs)181 int Q_ColorStrLastStyle (char *s, int byteOfs)
182 {
183 	char	*end;
184 	int		lastStyle;
185 
186 	end = s + (byteOfs);	// don't check last byte
187 	lastStyle = 0;
188 	for ( ; *s && s<end ; s++) {
189 		if ((s[0] & 127) != COLOR_ESCAPE)
190 			continue;
191 
192 		switch (s[1] & 127) {
193 		case 'i':	case 'I':
194 			lastStyle ^= FS_ITALIC;
195 			break;
196 		case 's':	case 'S':
197 			lastStyle ^= FS_SHADOW;
198 			break;
199 		case 'r':	case 'R':
200 			lastStyle = 0;
201 			break;
202 		default:
203 			continue;
204 		}
205 
206 		s++;
207 	}
208 
209 	return lastStyle;
210 }
211 
212 /*
213 ============================================================================
214 
215 	LIBRARY REPLACEMENT FUNCTIONS
216 
217 ============================================================================
218 */
219 
220 /*
221 ===============
222 Q_snprintfz
223 ===============
224 */
Q_snprintfz(char * dest,size_t size,const char * fmt,...)225 void Q_snprintfz (char *dest, size_t size, const char *fmt, ...)
226 {
227 	if (size) {
228 		va_list		argptr;
229 
230 		va_start (argptr, fmt);
231 		vsnprintf (dest, size, fmt, argptr);
232 		va_end (argptr);
233 
234 		dest[size-1] = '\0';
235 	}
236 }
237 
238 
239 /*
240 ===============
241 Q_strcatz
242 ===============
243 */
Q_strcatz(char * dst,const char * src,int dstSize)244 void Q_strcatz (char *dst, const char *src, int dstSize)
245 {
246 	int		len;
247 
248 	len = strlen (dst);
249 	if (len >= dstSize) {
250 		Com_Printf (PRNT_ERROR, "Q_strcatz: already overflowed");
251 		return;
252 	}
253 
254 	Q_strncpyz (dst + len, src, dstSize - len);
255 }
256 
257 
258 /*
259 ===============
260 Q_strncpyz
261 ===============
262 */
Q_strncpyz(char * dest,const char * src,size_t size)263 void Q_strncpyz (char *dest, const char *src, size_t size)
264 {
265 #ifdef HAVE_STRLCPY
266 	strlcpy (dest, src, size);
267 #else
268 	if (size) {
269 		while (--size && (*dest++ = *src++)) ;
270 		*dest = '\0';
271 	}
272 #endif
273 }
274 
275 
276 /*
277 ===============
278 Q_strlwr
279 ===============
280 */
Q_strlwr(char * s)281 char *Q_strlwr (char *s)
282 {
283 	char *p;
284 
285 	if (s) {
286 		for (p=s ; *s ; s++)
287 			*s = Q_tolower (*s);
288 		return p;
289 	}
290 
291 	return NULL;
292 }
293 
294 
295 /*
296 ===============
297 Q_tolower
298 
299 by R1CH
300 ===============
301 */
302 #ifdef id386
Q_tolower(int c)303 __declspec(naked) int __cdecl Q_tolower (int c)
304 {
305 	__asm {
306 			mov eax, [esp+4]		;get character
307 			cmp	eax, 5Ah
308 			ja  short finish1
309 
310 			cmp	eax, 41h
311 			jb  short finish1
312 
313 			or  eax, 00100000b		;to lower (-32)
314 		finish1:
315 			ret
316 	}
317 }
318 #endif // id386
319 
320 // =========================================================================
321 
322 /*
323 ============
324 Q_WildcardMatch
325 
326 from Q2ICE
327 ============
328 */
Q_WildcardMatch(const char * filter,const char * string,int ignoreCase)329 int Q_WildcardMatch (const char *filter, const char *string, int ignoreCase)
330 {
331 	switch (*filter) {
332 	case '\0':	return !*string;
333 	case '*':	return Q_WildcardMatch (filter + 1, string, ignoreCase) || *string && Q_WildcardMatch (filter, string + 1, ignoreCase);
334 	case '?':	return *string && Q_WildcardMatch (filter + 1, string + 1, ignoreCase);
335 	default:	return (*filter == *string || (ignoreCase && toupper (*filter) == toupper (*string))) && Q_WildcardMatch (filter + 1, string + 1, ignoreCase);
336 	}
337 }
338 
339 
340 /*
341 ============
342 Q_VarArgs
343 
344 Does a varargs printf into a temp buffer, so I don't need to have
345 varargs versions of all text functions.
346 ============
347 */
Q_VarArgs(char * format,...)348 char *Q_VarArgs (char *format, ...)
349 {
350 	va_list		argptr;
351 	static char	string[2][1024];
352 	static int	strIndex;
353 
354 	strIndex ^= 1;
355 
356 	va_start (argptr, format);
357 	vsnprintf (string[strIndex], sizeof (string[strIndex]), format, argptr);
358 	va_end (argptr);
359 
360 	return string[strIndex];
361 }
362