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