DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
common.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3Copyright (C) 2000-2020 DarkPlaces contributors
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20*/
21// common.c -- misc functions used in client and server
22
23#include <stdlib.h>
24#include <fcntl.h>
25#ifndef WIN32
26#include <unistd.h>
27#endif
28
29#include "quakedef.h"
30#include "utf8lib.h"
31
32cvar_t registered = {CF_CLIENT | CF_SERVER | CF_READONLY, "registered","0", "indicates if this is running registered quake (whether gfx/pop.lmp was found)"};
33cvar_t cmdline = {CF_CLIENT | CF_SERVER | CF_READONLY, "cmdline","0", "contains commandline the engine was launched with"};
34
35// FIXME: Find a better place for these.
36cvar_t cl_playermodel = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "playermodel", "", "current player model in Nexuiz/Xonotic"};
37cvar_t cl_playerskin = {CF_CLIENT | CF_SERVER | CF_USERINFO | CF_ARCHIVE, "playerskin", "", "current player skin in Nexuiz/Xonotic"};
38
41
42//===========================================================================
43
45{
46 buf->cursize = 0;
47}
48
49unsigned char *SZ_GetSpace (sizebuf_t *buf, int length)
50{
51 unsigned char *data;
52
53 if (buf->cursize + length > buf->maxsize)
54 {
55 if (!buf->allowoverflow)
56 Host_Error ("SZ_GetSpace: overflow without allowoverflow set");
57
58 if (length > buf->maxsize)
59 Host_Error ("SZ_GetSpace: %i is > full buffer size", length);
60
61 buf->overflowed = true;
62 Con_Print("SZ_GetSpace: overflow\n");
63 SZ_Clear (buf);
64 }
65
66 data = buf->data + buf->cursize;
67 buf->cursize += length;
68
69 return data;
70}
71
72void SZ_Write (sizebuf_t *buf, const unsigned char *data, int length)
73{
75}
76
77// LadyHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
78// attention, it has been eradicated from here, its only (former) use in
79// all of darkplaces.
80
81static const char *hexchar = "0123456789ABCDEF";
82void Com_HexDumpToConsole(const unsigned char *data, int size)
83{
84 int i, j, n;
85 char text[1024];
86 char *cur, *flushpointer;
87 const unsigned char *d;
88 cur = text;
89 flushpointer = text + 512;
90 for (i = 0;i < size;)
91 {
92 n = 16;
93 if (n > size - i)
94 n = size - i;
95 d = data + i;
96 // print offset
97 *cur++ = hexchar[(i >> 12) & 15];
98 *cur++ = hexchar[(i >> 8) & 15];
99 *cur++ = hexchar[(i >> 4) & 15];
100 *cur++ = hexchar[(i >> 0) & 15];
101 *cur++ = ':';
102 // print hex
103 for (j = 0;j < 16;j++)
104 {
105 if (j < n)
106 {
107 *cur++ = hexchar[(d[j] >> 4) & 15];
108 *cur++ = hexchar[(d[j] >> 0) & 15];
109 }
110 else
111 {
112 *cur++ = ' ';
113 *cur++ = ' ';
114 }
115 if ((j & 3) == 3)
116 *cur++ = ' ';
117 }
118 // print text
119 for (j = 0;j < 16;j++)
120 {
121 if (j < n)
122 {
123 // color change prefix character has to be treated specially
124 if (d[j] == STRING_COLOR_TAG)
125 {
126 *cur++ = STRING_COLOR_TAG;
127 *cur++ = STRING_COLOR_TAG;
128 }
129 else if (d[j] >= (unsigned char) ' ')
130 *cur++ = d[j];
131 else
132 *cur++ = '.';
133 }
134 else
135 *cur++ = ' ';
136 }
137 *cur++ = '\n';
138 i += n;
139 if (cur >= flushpointer || i >= size)
140 {
141 *cur++ = 0;
142 Con_Print(text);
143 cur = text;
144 }
145 }
146}
147
149{
150 Com_HexDumpToConsole(buf->data, buf->cursize);
151}
152
153
154//============================================================================
155
156/*
157==============
158COM_Wordwrap
159
160Word wraps a string. The wordWidth function is guaranteed to be called exactly
161once for each word in the string, so it may be stateful, no idea what that
162would be good for any more. At the beginning of the string, it will be called
163for the char 0 to initialize a clean state, and then once with the string " "
164(a space) so the routine knows how long a space is.
165
166In case no single character fits into the given width, the wordWidth function
167must return the width of exactly one character.
168
169Wrapped lines get the isContinuation flag set and are continuationWidth less wide.
170
171The sum of the return values of the processLine function will be returned.
172==============
173*/
174int COM_Wordwrap(const char *string, size_t length, float continuationWidth, float maxWidth, COM_WordWidthFunc_t wordWidth, void *passthroughCW, COM_LineProcessorFunc processLine, void *passthroughPL)
175{
176 // Logic is as follows:
177 //
178 // For each word or whitespace:
179 // Newline found? Output current line, advance to next line. This is not a continuation. Continue.
180 // Space found? Always add it to the current line, no matter if it fits.
181 // Word found? Check if current line + current word fits.
182 // If it fits, append it. Continue.
183 // If it doesn't fit, output current line, advance to next line. Append the word. This is a continuation. Continue.
184
185 qbool isContinuation = false;
186 float spaceWidth;
187 const char *startOfLine = string;
188 const char *cursor = string;
189 const char *end = string + length;
190 float spaceUsedInLine = 0;
191 float spaceUsedForWord;
192 int result = 0;
193 size_t wordLen;
194 size_t dummy;
195
196 dummy = 0;
197 wordWidth(passthroughCW, NULL, &dummy, -1);
198 dummy = 1;
199 spaceWidth = wordWidth(passthroughCW, " ", &dummy, -1);
200
201 for(;;)
202 {
203 char ch = (cursor < end) ? *cursor : 0;
204 switch(ch)
205 {
206 case 0: // end of string
207 result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
208 goto out;
209 case '\n': // end of line
210 result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
211 isContinuation = false;
212 ++cursor;
213 startOfLine = cursor;
214 break;
215 case ' ': // space
216 ++cursor;
217 spaceUsedInLine += spaceWidth;
218 break;
219 default: // word
220 wordLen = 1;
221 while(cursor + wordLen < end)
222 {
223 switch(cursor[wordLen])
224 {
225 case 0:
226 case '\n':
227 case ' ':
228 goto out_inner;
229 default:
230 ++wordLen;
231 break;
232 }
233 }
234 out_inner:
235 spaceUsedForWord = wordWidth(passthroughCW, cursor, &wordLen, maxWidth - continuationWidth); // this may have reduced wordLen when it won't fit - but this is GOOD. TODO fix words that do fit in a non-continuation line
236 if(wordLen < 1) // cannot happen according to current spec of wordWidth
237 {
238 wordLen = 1;
239 spaceUsedForWord = maxWidth + 1; // too high, forces it in a line of itself
240 }
241 if(spaceUsedInLine + spaceUsedForWord <= maxWidth || cursor == startOfLine)
242 {
243 // we can simply append it
244 cursor += wordLen;
245 spaceUsedInLine += spaceUsedForWord;
246 }
247 else
248 {
249 // output current line
250 result += processLine(passthroughPL, startOfLine, cursor - startOfLine, spaceUsedInLine, isContinuation);
251 isContinuation = true;
252 startOfLine = cursor;
253 cursor += wordLen;
254 spaceUsedInLine = continuationWidth + spaceUsedForWord;
255 }
256 }
257 }
258 out:
259
260 return result;
261
262/*
263 qbool isContinuation = false;
264 float currentWordSpace = 0;
265 const char *currentWord = 0;
266 float minReserve = 0;
267
268 float spaceUsedInLine = 0;
269 const char *currentLine = 0;
270 const char *currentLineEnd = 0;
271 float currentLineFinalWhitespace = 0;
272 const char *p;
273
274 int result = 0;
275 minReserve = charWidth(passthroughCW, 0);
276 minReserve += charWidth(passthroughCW, ' ');
277
278 if(maxWidth < continuationWidth + minReserve)
279 maxWidth = continuationWidth + minReserve;
280
281 charWidth(passthroughCW, 0);
282
283 for(p = string; p < string + length; ++p)
284 {
285 char c = *p;
286 float w = charWidth(passthroughCW, c);
287
288 if(!currentWord)
289 {
290 currentWord = p;
291 currentWordSpace = 0;
292 }
293
294 if(!currentLine)
295 {
296 currentLine = p;
297 spaceUsedInLine = isContinuation ? continuationWidth : 0;
298 currentLineEnd = 0;
299 }
300
301 if(c == ' ')
302 {
303 // 1. I can add the word AND a space - then just append it.
304 if(spaceUsedInLine + currentWordSpace + w <= maxWidth)
305 {
306 currentLineEnd = p; // note: space not included here
307 currentLineFinalWhitespace = w;
308 spaceUsedInLine += currentWordSpace + w;
309 }
310 // 2. I can just add the word - then append it, output current line and go to next one.
311 else if(spaceUsedInLine + currentWordSpace <= maxWidth)
312 {
313 result += processLine(passthroughPL, currentLine, p - currentLine, spaceUsedInLine + currentWordSpace, isContinuation);
314 currentLine = 0;
315 isContinuation = true;
316 }
317 // 3. Otherwise, output current line and go to next one, where I can add the word.
318 else if(continuationWidth + currentWordSpace + w <= maxWidth)
319 {
320 if(currentLineEnd)
321 result += processLine(passthroughPL, currentLine, currentLineEnd - currentLine, spaceUsedInLine - currentLineFinalWhitespace, isContinuation);
322 currentLine = currentWord;
323 spaceUsedInLine = continuationWidth + currentWordSpace + w;
324 currentLineEnd = p;
325 currentLineFinalWhitespace = w;
326 isContinuation = true;
327 }
328 // 4. We can't even do that? Then output both current and next word as new lines.
329 else
330 {
331 if(currentLineEnd)
332 {
333 result += processLine(passthroughPL, currentLine, currentLineEnd - currentLine, spaceUsedInLine - currentLineFinalWhitespace, isContinuation);
334 isContinuation = true;
335 }
336 result += processLine(passthroughPL, currentWord, p - currentWord, currentWordSpace, isContinuation);
337 currentLine = 0;
338 isContinuation = true;
339 }
340 currentWord = 0;
341 }
342 else if(c == '\n')
343 {
344 // 1. I can add the word - then do it.
345 if(spaceUsedInLine + currentWordSpace <= maxWidth)
346 {
347 result += processLine(passthroughPL, currentLine, p - currentLine, spaceUsedInLine + currentWordSpace, isContinuation);
348 }
349 // 2. Otherwise, output current line, next one and make tabula rasa.
350 else
351 {
352 if(currentLineEnd)
353 {
354 processLine(passthroughPL, currentLine, currentLineEnd - currentLine, spaceUsedInLine - currentLineFinalWhitespace, isContinuation);
355 isContinuation = true;
356 }
357 result += processLine(passthroughPL, currentWord, p - currentWord, currentWordSpace, isContinuation);
358 }
359 currentWord = 0;
360 currentLine = 0;
361 isContinuation = false;
362 }
363 else
364 {
365 currentWordSpace += w;
366 if(
367 spaceUsedInLine + currentWordSpace > maxWidth // can't join this line...
368 &&
369 continuationWidth + currentWordSpace > maxWidth // can't join any other line...
370 )
371 {
372 // this word cannot join ANY line...
373 // so output the current line...
374 if(currentLineEnd)
375 {
376 result += processLine(passthroughPL, currentLine, currentLineEnd - currentLine, spaceUsedInLine - currentLineFinalWhitespace, isContinuation);
377 isContinuation = true;
378 }
379
380 // then this word's beginning...
381 if(isContinuation)
382 {
383 // it may not fit, but we know we have to split it into maxWidth - continuationWidth pieces
384 float pieceWidth = maxWidth - continuationWidth;
385 const char *pos = currentWord;
386 currentWordSpace = 0;
387
388 // reset the char width function to a state where no kerning occurs (start of word)
389 charWidth(passthroughCW, ' ');
390 while(pos <= p)
391 {
392 float w = charWidth(passthroughCW, *pos);
393 if(currentWordSpace + w > pieceWidth) // this piece won't fit any more
394 {
395 // print everything until it
396 result += processLine(passthroughPL, currentWord, pos - currentWord, currentWordSpace, true);
397 // go to here
398 currentWord = pos;
399 currentWordSpace = 0;
400 }
401 currentWordSpace += w;
402 ++pos;
403 }
404 // now we have a currentWord that fits... set up its next line
405 // currentWordSpace has been set
406 // currentWord has been set
407 spaceUsedInLine = continuationWidth;
408 currentLine = currentWord;
409 currentLineEnd = 0;
410 isContinuation = true;
411 }
412 else
413 {
414 // we have a guarantee that it will fix (see if clause)
415 result += processLine(passthroughPL, currentWord, p - currentWord, currentWordSpace - w, isContinuation);
416
417 // and use the rest of this word as new start of a line
418 currentWordSpace = w;
419 currentWord = p;
420 spaceUsedInLine = continuationWidth;
421 currentLine = p;
422 currentLineEnd = 0;
423 isContinuation = true;
424 }
425 }
426 }
427 }
428
429 if(!currentWord)
430 {
431 currentWord = p;
432 currentWordSpace = 0;
433 }
434
435 if(currentLine) // Same procedure as \n
436 {
437 // Can I append the current word?
438 if(spaceUsedInLine + currentWordSpace <= maxWidth)
439 result += processLine(passthroughPL, currentLine, p - currentLine, spaceUsedInLine + currentWordSpace, isContinuation);
440 else
441 {
442 if(currentLineEnd)
443 {
444 result += processLine(passthroughPL, currentLine, currentLineEnd - currentLine, spaceUsedInLine - currentLineFinalWhitespace, isContinuation);
445 isContinuation = true;
446 }
447 result += processLine(passthroughPL, currentWord, p - currentWord, currentWordSpace, isContinuation);
448 }
449 }
450
451 return result;
452*/
453}
454
455/*
456==============
457COM_ParseToken_Simple
458
459Parse a token out of a string
460Writes the token and its strlen to the com_token and com_token_len globals.
461==============
462*/
463qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
464{
465 int len;
466 int c;
467 const char *data = *datapointer;
468
469 com_token_len = len = 0;
470 com_token[0] = '\0';
471
472 if (!data)
473 {
474 *datapointer = NULL;
475 return false;
476 }
477
478// skip whitespace
479skipwhite:
480 // line endings:
481 // UNIX: \n
482 // Mac: \r
483 // Windows: \r\n
484 for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
485 {
486 if (*data == 0)
487 {
488 // end of file
489 *datapointer = NULL;
490 return false;
491 }
492 }
493
494 // handle Windows line ending
495 if (data[0] == '\r' && data[1] == '\n')
496 data++;
497
498 if (parsecomments && data[0] == '/' && data[1] == '/')
499 {
500 // comment
501 while (*data && *data != '\n' && *data != '\r')
502 data++;
503 goto skipwhite;
504 }
505 else if (parsecomments && data[0] == '/' && data[1] == '*')
506 {
507 // comment
508 data++;
509 while (*data && (data[0] != '*' || data[1] != '/'))
510 data++;
511 if (*data)
512 data++;
513 if (*data)
514 data++;
515 goto skipwhite;
516 }
517 else if (*data == '\"')
518 {
519 // quoted string
520 for (data++;*data && *data != '\"';data++)
521 {
522 c = *data;
523 if (*data == '\\' && parsebackslash)
524 {
525 data++;
526 c = *data;
527 if (c == 'n')
528 c = '\n';
529 else if (c == 't')
530 c = '\t';
531 }
532 if (len < (int)sizeof(com_token) - 1)
533 com_token[len++] = c;
534 }
535 com_token[len] = '\0';
536 com_token_len = len;
537 if (*data == '\"')
538 data++;
539 *datapointer = data;
540 return true;
541 }
542 else if (*data == '\r')
543 {
544 // translate Mac line ending to UNIX
545 com_token[len++] = '\n';data++;
546 com_token[len] = '\0';
547 com_token_len = len;
548 *datapointer = data;
549 return true;
550 }
551 else if (*data == '\n')
552 {
553 // single character
554 com_token[len++] = *data++;
555 com_token[len] = '\0';
556 com_token_len = len;
557 *datapointer = data;
558 return true;
559 }
560 else
561 {
562 // regular word
563 for (;!ISWHITESPACE(*data);data++)
564 if (len < (int)sizeof(com_token) - 1)
565 com_token[len++] = *data;
566 com_token[len] = '\0';
567 com_token_len = len;
568 *datapointer = data;
569 return true;
570 }
571}
572
573/*
574==============
575COM_ParseToken_QuakeC
576
577Parse a token out of a string
578Writes the token and its strlen to the com_token and com_token_len globals.
579==============
580*/
581qbool COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
582{
583 int len;
584 int c;
585 const char *data = *datapointer;
586
587 com_token_len = len = 0;
588 com_token[0] = '\0';
589
590 if (!data)
591 {
592 *datapointer = NULL;
593 return false;
594 }
595
596// skip whitespace
597skipwhite:
598 // line endings:
599 // UNIX: \n
600 // Mac: \r
601 // Windows: \r\n
602 for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
603 {
604 if (*data == 0)
605 {
606 // end of file
607 *datapointer = NULL;
608 return false;
609 }
610 }
611
612 // handle Windows line ending
613 if (data[0] == '\r' && data[1] == '\n')
614 data++;
615
616 if (data[0] == '/' && data[1] == '/')
617 {
618 // comment
619 while (*data && *data != '\n' && *data != '\r')
620 data++;
621 goto skipwhite;
622 }
623 else if (data[0] == '/' && data[1] == '*')
624 {
625 // comment
626 data++;
627 while (*data && (data[0] != '*' || data[1] != '/'))
628 data++;
629 if (*data)
630 data++;
631 if (*data)
632 data++;
633 goto skipwhite;
634 }
635 else if (*data == '\"' || *data == '\'')
636 {
637 // quoted string
638 char quote = *data;
639 for (data++;*data && *data != quote;data++)
640 {
641 c = *data;
642 if (*data == '\\')
643 {
644 data++;
645 c = *data;
646 if (c == 'n')
647 c = '\n';
648 else if (c == 't')
649 c = '\t';
650 }
651 if (len < (int)sizeof(com_token) - 1)
652 com_token[len++] = c;
653 }
654 com_token[len] = '\0';
655 com_token_len = len;
656 if (*data == quote)
657 data++;
658 *datapointer = data;
659 return true;
660 }
661 else if (*data == '\r')
662 {
663 // translate Mac line ending to UNIX
664 com_token[len++] = '\n';data++;
665 com_token[len] = '\0';
666 com_token_len = len;
667 *datapointer = data;
668 return true;
669 }
670 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == ':' || *data == ',' || *data == ';')
671 {
672 // single character
673 com_token[len++] = *data++;
674 com_token[len] = '\0';
675 com_token_len = len;
676 *datapointer = data;
677 return true;
678 }
679 else
680 {
681 // regular word
682 for (;!ISWHITESPACE(*data) && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
683 if (len < (int)sizeof(com_token) - 1)
684 com_token[len++] = *data;
685 com_token[len] = '\0';
686 com_token_len = len;
687 *datapointer = data;
688 return true;
689 }
690}
691
692/*
693==============
694COM_ParseToken_VM_Tokenize
695
696Parse a token out of a string
697Writes the token and its strlen to the com_token and com_token_len globals.
698==============
699*/
700qbool COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline)
701{
702 int len;
703 int c;
704 const char *data = *datapointer;
705
706 com_token_len = len = 0;
707 com_token[0] = '\0';
708
709 if (!data)
710 {
711 *datapointer = NULL;
712 return false;
713 }
714
715// skip whitespace
716skipwhite:
717 // line endings:
718 // UNIX: \n
719 // Mac: \r
720 // Windows: \r\n
721 for (;ISWHITESPACE(*data) && ((*data != '\n' && *data != '\r') || !returnnewline);data++)
722 {
723 if (*data == 0)
724 {
725 // end of file
726 *datapointer = NULL;
727 return false;
728 }
729 }
730
731 // handle Windows line ending
732 if (data[0] == '\r' && data[1] == '\n')
733 data++;
734
735 if (data[0] == '/' && data[1] == '/')
736 {
737 // comment
738 while (*data && *data != '\n' && *data != '\r')
739 data++;
740 goto skipwhite;
741 }
742 else if (data[0] == '/' && data[1] == '*')
743 {
744 // comment
745 data++;
746 while (*data && (data[0] != '*' || data[1] != '/'))
747 data++;
748 if (*data)
749 data++;
750 if (*data)
751 data++;
752 goto skipwhite;
753 }
754 else if (*data == '\"' || *data == '\'')
755 {
756 char quote = *data;
757 // quoted string
758 for (data++;*data && *data != quote;data++)
759 {
760 c = *data;
761 if (*data == '\\')
762 {
763 data++;
764 c = *data;
765 if (c == 'n')
766 c = '\n';
767 else if (c == 't')
768 c = '\t';
769 }
770 if (len < (int)sizeof(com_token) - 1)
771 com_token[len++] = c;
772 }
773 com_token[len] = '\0';
774 com_token_len = len;
775 if (*data == quote)
776 data++;
777 *datapointer = data;
778 return true;
779 }
780 else if (*data == '\r')
781 {
782 // translate Mac line ending to UNIX
783 com_token[len++] = '\n';data++;
784 com_token[len] = '\0';
785 com_token_len = len;
786 *datapointer = data;
787 return true;
788 }
789 else if (*data == '\n' || *data == '{' || *data == '}' || *data == ')' || *data == '(' || *data == ']' || *data == '[' || *data == ':' || *data == ',' || *data == ';')
790 {
791 // single character
792 com_token[len++] = *data++;
793 com_token[len] = '\0';
794 com_token_len = len;
795 *datapointer = data;
796 return true;
797 }
798 else
799 {
800 // regular word
801 for (;!ISWHITESPACE(*data) && *data != '{' && *data != '}' && *data != ')' && *data != '(' && *data != ']' && *data != '[' && *data != ':' && *data != ',' && *data != ';';data++)
802 if (len < (int)sizeof(com_token) - 1)
803 com_token[len++] = *data;
804 com_token[len] = '\0';
805 com_token_len = len;
806 *datapointer = data;
807 return true;
808 }
809}
810
811/*
812==============
813COM_ParseToken_Console
814
815Parse a token out of a string, behaving like the qwcl console
816Writes the token and its strlen to the com_token and com_token_len globals.
817==============
818*/
819qbool COM_ParseToken_Console(const char **datapointer)
820{
821 int len;
822 const char *data = *datapointer;
823
824 com_token_len = len = 0;
825 com_token[0] = '\0';
826
827 if (!data)
828 {
829 *datapointer = NULL;
830 return false;
831 }
832
833// skip whitespace
834skipwhite:
835 for (;ISWHITESPACE(*data);data++)
836 {
837 if (*data == 0)
838 {
839 // end of file
840 *datapointer = NULL;
841 return false;
842 }
843 }
844
845 if (*data == '/' && data[1] == '/')
846 {
847 // comment
848 while (*data && *data != '\n' && *data != '\r')
849 data++;
850 goto skipwhite;
851 }
852 else if (*data == '\"')
853 {
854 // quoted string
855 for (data++;*data && *data != '\"';data++)
856 {
857 // allow escaped " and \ case
858 if (*data == '\\' && (data[1] == '\"' || data[1] == '\\'))
859 data++;
860 if (len < (int)sizeof(com_token) - 1)
861 com_token[len++] = *data;
862 }
863 com_token[len] = '\0';
864 com_token_len = len;
865 if (*data == '\"')
866 data++;
867 *datapointer = data;
868 }
869 else
870 {
871 // regular word
872 for (;!ISWHITESPACE(*data);data++)
873 if (len < (int)sizeof(com_token) - 1)
874 com_token[len++] = *data;
875 com_token[len] = '\0';
876 com_token_len = len;
877 *datapointer = data;
878 }
879
880 return true;
881}
882
883/*
884===============
885Com_CalcRoll
886
887Used by view and sv_user
888===============
889*/
890float Com_CalcRoll (const vec3_t angles, const vec3_t velocity, const vec_t angleval, const vec_t velocityval)
891{
893 float sign;
894 float side;
895
897 side = DotProduct (velocity, right);
898 sign = side < 0 ? -1 : 1;
899 side = fabs(side);
900
901 if (side < velocityval)
902 side = side * angleval / velocityval;
903 else
904 side = angleval;
905
906 return side*sign;
907
908}
909
910//===========================================================================
911
912/*
913================
914COM_Init
915================
916*/
918{
919 int i, j, n;
920 char com_cmdline[MAX_INPUTLINE];
921
925 Cvar_RegisterVirtual(&cl_playermodel, "_cl_playermodel");
927 Cvar_RegisterVirtual(&cl_playerskin, "_cl_playerskin");
928
929 // reconstitute the command line for the cmdline externally visible cvar
930 n = 0;
931 for (j = 0;(j < MAX_NUM_ARGVS) && (j < sys.argc);j++)
932 {
933 i = 0;
934 if (strstr(sys.argv[j], " "))
935 {
936 // arg contains whitespace, store quotes around it
937 // This condition checks whether we can allow to put
938 // in two quote characters.
939 if (n >= ((int)sizeof(com_cmdline) - 2))
940 break;
941 com_cmdline[n++] = '\"';
942 // This condition checks whether we can allow one
943 // more character and a quote character.
944 while ((n < ((int)sizeof(com_cmdline) - 2)) && sys.argv[j][i])
945 // FIXME: Doesn't quote special characters.
946 com_cmdline[n++] = sys.argv[j][i++];
947 com_cmdline[n++] = '\"';
948 }
949 else
950 {
951 // This condition checks whether we can allow one
952 // more character.
953 while ((n < ((int)sizeof(com_cmdline) - 1)) && sys.argv[j][i])
954 com_cmdline[n++] = sys.argv[j][i++];
955 }
956 if (n < ((int)sizeof(com_cmdline) - 1))
957 com_cmdline[n++] = ' ';
958 else
959 break;
960 }
961 com_cmdline[n] = 0;
962 Cvar_SetQuick(&cmdline, com_cmdline);
963}
964
965/*
966============
967va
968
969varargs print into provided buffer, returns buffer (so that it can be called in-line, unlike dpsnprintf)
970============
971*/
972char *va(char *buf, size_t buflen, const char *format, ...)
973{
974 va_list argptr;
975
976 va_start (argptr, format);
977 dpvsnprintf (buf, buflen, format,argptr);
978 va_end (argptr);
979
980 return buf;
981}
982
983
984//======================================
985
986// snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
987
988#undef snprintf
989#undef vsnprintf
990
991#ifdef WIN32
992# define snprintf _snprintf
993# define vsnprintf _vsnprintf
994#endif
995
996
997int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...)
998{
999 va_list args;
1000 int result;
1001
1002 va_start (args, format);
1003 result = dpvsnprintf (buffer, buffersize, format, args);
1004 va_end (args);
1005
1006 return result;
1007}
1008
1009
1010int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args)
1011{
1012 int result;
1013
1014#if _MSC_VER >= 1400
1015 result = _vsnprintf_s (buffer, buffersize, _TRUNCATE, format, args);
1016#else
1017 result = vsnprintf (buffer, buffersize, format, args);
1018#endif
1019 if (result < 0 || (size_t)result >= buffersize)
1020 {
1021 // _vsnprintf_s returns -1 on error and on truncation (indistinguishable),
1022 // vsnprintf returns negative on error and the desired strlen on truncation.
1023 buffer[buffersize - 1] = '\0'; // should be unnecessary, but just in case
1024 // Basic stdout only: we could be inside Con_Printf, Sys_Printf calls dpvsnprintf,
1025 // Windows console doesn't support colours.
1026 if (result < 0)
1027 Sys_Print("dpvsnprintf: output error!\n", 27);
1028 else
1029 {
1030 char msg[MAX_INPUTLINE];
1031#if _MSC_VER >= 1400
1032 result = _snprintf_s(msg, sizeof(msg), _TRUNCATE, "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer);
1033#else
1034 result = snprintf(msg, sizeof(msg), "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer);
1035#endif
1036 if (result > 0)
1037 {
1038 msg[sizeof(msg) - 1] = '\n'; // may have been lost in truncation
1039 Sys_Print(msg, min((size_t)result, sizeof(msg) - 1));
1040 }
1041 }
1042 return -1;
1043 }
1044
1045 return result;
1046}
1047
1048
1049//======================================
1050
1051size_t COM_ToLowerString(const char *in, char *out, size_t size_out)
1052{
1053 const char *out_start = out;
1054
1055 if (size_out == 0)
1056 return 0;
1057
1059 {
1060 *out = 0;
1061 while(*in && size_out > 1)
1062 {
1063 int n;
1064 Uchar ch = u8_getchar_utf8_enabled(in, &in);
1065 ch = u8_tolower(ch);
1066 n = u8_fromchar(ch, out, size_out);
1067 out += n; // before the break so the return is correct
1068 if(n <= 0)
1069 break;
1070 size_out -= n;
1071 }
1072 return out - out_start;
1073 }
1074
1075 while (*in && size_out > 1)
1076 {
1077 if (*in >= 'A' && *in <= 'Z')
1078 *out++ = *in++ + 'a' - 'A';
1079 else
1080 *out++ = *in++;
1081 size_out--;
1082 }
1083 *out = '\0';
1084 return out - out_start;
1085}
1086
1087size_t COM_ToUpperString(const char *in, char *out, size_t size_out)
1088{
1089 const char *out_start = out;
1090
1091 if (size_out == 0)
1092 return 0;
1093
1095 {
1096 *out = 0;
1097 while(*in && size_out > 1)
1098 {
1099 int n;
1100 Uchar ch = u8_getchar_utf8_enabled(in, &in);
1101 ch = u8_toupper(ch);
1102 n = u8_fromchar(ch, out, size_out);
1103 out += n; // before the break so the return is correct
1104 if(n <= 0)
1105 break;
1106 size_out -= n;
1107 }
1108 return out - out_start;
1109 }
1110
1111 while (*in && size_out > 1)
1112 {
1113 if (*in >= 'a' && *in <= 'z')
1114 *out++ = *in++ + 'A' - 'a';
1115 else
1116 *out++ = *in++;
1117 size_out--;
1118 }
1119 *out = '\0';
1120 return out - out_start;
1121}
1122
1123int COM_StringBeginsWith(const char *s, const char *match)
1124{
1125 for (;*s && *match;s++, match++)
1126 if (*s != *match)
1127 return false;
1128 return true;
1129}
1130
1131int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
1132{
1133 int argc, commentprefixlength;
1134 char *tokenbufend;
1135 const char *l;
1136 argc = 0;
1137 tokenbufend = tokenbuf + tokenbufsize;
1138 l = *text;
1139 commentprefixlength = 0;
1140 if (commentprefix)
1141 commentprefixlength = (int)strlen(commentprefix);
1142 while (*l && *l != '\n' && *l != '\r')
1143 {
1144 if (!ISWHITESPACE(*l))
1145 {
1146 if (commentprefixlength && !strncmp(l, commentprefix, commentprefixlength))
1147 {
1148 while (*l && *l != '\n' && *l != '\r')
1149 l++;
1150 break;
1151 }
1152 if (argc >= maxargc)
1153 return -1;
1154 argv[argc++] = tokenbuf;
1155 if (*l == '"')
1156 {
1157 l++;
1158 while (*l && *l != '"')
1159 {
1160 if (tokenbuf >= tokenbufend)
1161 return -1;
1162 *tokenbuf++ = *l++;
1163 }
1164 if (*l == '"')
1165 l++;
1166 }
1167 else
1168 {
1169 while (!ISWHITESPACE(*l))
1170 {
1171 if (tokenbuf >= tokenbufend)
1172 return -1;
1173 *tokenbuf++ = *l++;
1174 }
1175 }
1176 if (tokenbuf >= tokenbufend)
1177 return -1;
1178 *tokenbuf++ = 0;
1179 }
1180 else
1181 l++;
1182 }
1183 // line endings:
1184 // UNIX: \n
1185 // Mac: \r
1186 // Windows: \r\n
1187 if (*l == '\r')
1188 l++;
1189 if (*l == '\n')
1190 l++;
1191 *text = l;
1192 return argc;
1193}
1194
1195/*
1196============
1197COM_StringLengthNoColors
1198
1199calculates the visible width of a color coded string.
1200
1201*valid is filled with TRUE if the string is a valid colored string (that is, if
1202it does not end with an unfinished color code). If it gets filled with FALSE, a
1203fix would be adding a STRING_COLOR_TAG at the end of the string.
1204
1205valid can be set to NULL if the caller doesn't care.
1206
1207For size_s, specify the maximum number of characters from s to use, or 0 to use
1208all characters until the zero terminator.
1209============
1210*/
1211size_t
1212COM_StringLengthNoColors(const char *s, size_t size_s, qbool *valid)
1213{
1214 const char *end = size_s ? (s + size_s) : NULL;
1215 size_t len = 0;
1216 for(;;)
1217 {
1218 switch((s == end) ? 0 : *s)
1219 {
1220 case 0:
1221 if(valid)
1222 *valid = true;
1223 return len;
1224 case STRING_COLOR_TAG:
1225 ++s;
1226 switch((s == end) ? 0 : *s)
1227 {
1229 if (s+1 != end && isxdigit(s[1]) &&
1230 s+2 != end && isxdigit(s[2]) &&
1231 s+3 != end && isxdigit(s[3]) )
1232 {
1233 s+=3;
1234 break;
1235 }
1236 ++len; // STRING_COLOR_TAG
1237 ++len; // STRING_COLOR_RGB_TAG_CHAR
1238 break;
1239 case 0: // ends with unfinished color code!
1240 ++len;
1241 if(valid)
1242 *valid = false;
1243 return len;
1244 case STRING_COLOR_TAG: // escaped ^
1245 ++len;
1246 break;
1247 case '0': case '1': case '2': case '3': case '4':
1248 case '5': case '6': case '7': case '8': case '9': // color code
1249 break;
1250 default: // not a color code
1251 ++len; // STRING_COLOR_TAG
1252 ++len; // the character
1253 break;
1254 }
1255 break;
1256 default:
1257 ++len;
1258 break;
1259 }
1260 ++s;
1261 }
1262 // never get here
1263}
1264
1265/*
1266============
1267COM_StringDecolorize
1268
1269removes color codes from a string.
1270
1271If escape_carets is true, the resulting string will be safe for printing. If
1272escape_carets is false, the function will just strip color codes (for logging
1273for example).
1274Returns the number of bytes written to the *out buffer excluding the \0 terminator.
1275
1276If the output buffer size did not suffice for converting, the function returns 0.
1277Generally, if escape_carets is false, the output buffer needs
1278strlen(str)+1 bytes, and if escape_carets is true, it can need strlen(str)*1.5+2
1279bytes. In any case, the function makes sure that the resulting string is
1280zero terminated.
1281
1282For size_in, specify the maximum number of characters from in to use, or 0 to use
1283all characters until the zero terminator.
1284============
1285*/
1286size_t COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
1287{
1288#define APPEND(ch) do { if(--size_out) { *out++ = (ch); } else { *out++ = 0; return 0; } } while(0)
1289
1290 const char *out_start = out;
1291 const char *end = size_in ? (in + size_in) : NULL;
1292
1293 if(size_out < 1)
1294 return 0;
1295 for(;;)
1296 {
1297 switch((in == end) ? 0 : *in)
1298 {
1299 case 0:
1300 *out = '\0';
1301 return out - out_start;
1302 case STRING_COLOR_TAG:
1303 ++in;
1304 switch((in == end) ? 0 : *in)
1305 {
1307 if (in+1 != end && isxdigit(in[1]) &&
1308 in+2 != end && isxdigit(in[2]) &&
1309 in+3 != end && isxdigit(in[3]) )
1310 {
1311 in+=3;
1312 break;
1313 }
1315 if(escape_carets)
1318 break;
1319 case 0: // ends with unfinished color code!
1321 // finish the code by appending another caret when escaping
1322 if(escape_carets)
1324 *out = '\0';
1325 return out - out_start;
1326 case STRING_COLOR_TAG: // escaped ^
1328 // append a ^ twice when escaping
1329 if(escape_carets)
1331 break;
1332 case '0': case '1': case '2': case '3': case '4':
1333 case '5': case '6': case '7': case '8': case '9': // color code
1334 break;
1335 default: // not a color code
1337 APPEND(*in);
1338 break;
1339 }
1340 break;
1341 default:
1342 APPEND(*in);
1343 break;
1344 }
1345 ++in;
1346 }
1347 // never get here
1348#undef APPEND
1349}
1350
1351
1352/*
1353============
1354String Copying
1355
1356The glibc implementation of memccpy is several times faster than old functions that
1357copy one byte at a time (even at -O3) and its advantage increases with string length.
1358============
1359*/
1360#ifdef WIN32
1361 // memccpy() is standard in POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD, C23.
1362 // Microsoft supports it, but apparently complains if we use it.
1363 #undef memccpy
1364 #define memccpy _memccpy
1365#endif
1366
1373char *dp_stpecpy(char *dst, char *end, const char *src)
1374{
1375 char *p = (char *)memccpy(dst, src, '\0', end - dst);
1376
1377 if (p)
1378 return p - 1;
1379 end[-1] = '\0';
1380 Con_Printf(CON_WARN "%s: src string unterminated or truncated to %lu bytes: \"%s\"\n", __func__, (unsigned long)(dst == end ? 0 : (end - dst) - 1), dst);
1381 return end;
1382}
1383
1388char *dp_ustr2stp(char *dst, size_t dsize, const char *src, size_t slen)
1389{
1390 if (slen >= dsize)
1391 {
1392 slen = dsize - 1;
1393 Con_Printf(CON_WARN "%s: src string truncated to %lu bytes: \"%.*s\"\n", __func__, (unsigned long)slen, (int)slen, src);
1394 }
1395 memcpy(dst, src, slen);
1396 dst[slen] = '\0';
1397 return &dst[slen];
1398}
1399
1406size_t dp__strlcpy(char *dst, const char *src, size_t dsize, const char *func, unsigned line)
1407{
1408 char *p = (char *)memccpy(dst, src, '\0', dsize);
1409
1410 if (p)
1411 return (p - 1) - dst;
1412 dst[dsize - 1] = '\0';
1413 Con_Printf(CON_WARN "%s:%u: src string unterminated or truncated to %lu bytes: \"%s\"\n", func, line, (unsigned long)dsize - 1, dst);
1414 return dsize - 1;
1415}
1416
1423size_t dp__strlcat(char *dst, const char *src, size_t dsize, const char *func, unsigned line)
1424{
1425 size_t offset;
1426 char *p = (char *)memchr(dst, '\0', dsize);
1427
1428 if (!p)
1429 p = dst;
1430 offset = p - dst;
1431 return dp__strlcpy(p, src, dsize - offset, func, line) + offset;
1432}
1433
1434
1435
1436void FindFraction(double val, int *num, int *denom, int denomMax)
1437{
1438 int i;
1439 double bestdiff;
1440 // initialize
1441 bestdiff = fabs(val);
1442 *num = 0;
1443 *denom = 1;
1444
1445 for(i = 1; i <= denomMax; ++i)
1446 {
1447 int inum = (int) floor(0.5 + val * i);
1448 double diff = fabs(val - inum / (double)i);
1449 if(diff < bestdiff)
1450 {
1451 bestdiff = diff;
1452 *num = inum;
1453 *denom = i;
1454 }
1455 }
1456}
1457
1458// decodes an XPM from C syntax
1459char **XPM_DecodeString(const char *in)
1460{
1461 static char *tokens[257];
1462 static char lines[257][512];
1463 size_t line = 0;
1464
1465 // skip until "{" token
1466 while(COM_ParseToken_QuakeC(&in, false) && strcmp(com_token, "{"));
1467
1468 // now, read in succession: string, comma-or-}
1469 while(COM_ParseToken_QuakeC(&in, false))
1470 {
1471 tokens[line] = lines[line];
1472 dp_strlcpy(lines[line++], com_token, sizeof(lines[0]));
1473 if(!COM_ParseToken_QuakeC(&in, false))
1474 return NULL;
1475 if(!strcmp(com_token, "}"))
1476 break;
1477 if(strcmp(com_token, ","))
1478 return NULL;
1479 if(line >= sizeof(tokens) / sizeof(tokens[0]))
1480 return NULL;
1481 }
1482
1483 return tokens;
1484}
1485
1486static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1487static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
1488{
1489 unsigned char i0 = (bytes > 0) ? in[0] : 0;
1490 unsigned char i1 = (bytes > 1) ? in[1] : 0;
1491 unsigned char i2 = (bytes > 2) ? in[2] : 0;
1492 unsigned char o0 = base64[i0 >> 2];
1493 unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077];
1494 unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077];
1495 unsigned char o3 = base64[i2 & 077];
1496 out[0] = (bytes > 0) ? o0 : '?';
1497 out[1] = (bytes > 0) ? o1 : '?';
1498 out[2] = (bytes > 1) ? o2 : '=';
1499 out[3] = (bytes > 2) ? o3 : '=';
1500}
1501
1502size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen)
1503{
1504 size_t blocks, i;
1505 // expand the out-buffer
1506 blocks = (buflen + 2) / 3;
1507 if(blocks*4 > outbuflen)
1508 return 0;
1509 for(i = blocks; i > 0; )
1510 {
1511 --i;
1512 base64_3to4(buf + 3*i, buf + 4*i, (int)(buflen - 3*i));
1513 }
1514 return blocks * 4;
1515}
#define CF_READONLY
cvar cannot be changed from the console or the command buffer, and is considered CF_PERSISTENT
Definition cmd.h:54
#define CF_USERINFO
command or cvar used to communicate userinfo to the server
Definition cmd.h:57
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
void SZ_Clear(sizebuf_t *buf)
Definition common.c:44
int dpvsnprintf(char *buffer, size_t buffersize, const char *format, va_list args)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:1010
unsigned com_token_len
Definition common.c:40
char * dp_ustr2stp(char *dst, size_t dsize, const char *src, size_t slen)
Copies a measured byte sequence (unterminated string) to a null-terminated string.
Definition common.c:1388
size_t dp__strlcpy(char *dst, const char *src, size_t dsize, const char *func, unsigned line)
Copies a string, like strlcpy() but with a better return: the number of bytes copied excluding the \0...
Definition common.c:1406
int COM_StringBeginsWith(const char *s, const char *match)
Definition common.c:1123
cvar_t cl_playerskin
Definition common.c:37
unsigned char * SZ_GetSpace(sizebuf_t *buf, int length)
Definition common.c:49
int COM_Wordwrap(const char *string, size_t length, float continuationWidth, float maxWidth, COM_WordWidthFunc_t wordWidth, void *passthroughCW, COM_LineProcessorFunc processLine, void *passthroughPL)
Definition common.c:174
char com_token[MAX_INPUTLINE]
Definition common.c:39
cvar_t cl_playermodel
Definition common.c:36
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
qbool COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
Definition common.c:581
char * dp_stpecpy(char *dst, char *end, const char *src)
Chain-copies a string with truncation and efficiency (compared to strlcat()).
Definition common.c:1373
char ** XPM_DecodeString(const char *in)
Definition common.c:1459
size_t COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qbool escape_carets)
Definition common.c:1286
qbool COM_ParseToken_VM_Tokenize(const char **datapointer, qbool returnnewline)
Definition common.c:700
qbool COM_ParseToken_Console(const char **datapointer)
Definition common.c:819
float Com_CalcRoll(const vec3_t angles, const vec3_t velocity, const vec_t angleval, const vec_t velocityval)
Definition common.c:890
size_t COM_ToUpperString(const char *in, char *out, size_t size_out)
Returns the number of bytes written to *out excluding the \0 terminator.
Definition common.c:1087
void Com_HexDumpToConsole(const unsigned char *data, int size)
Definition common.c:82
void SZ_HexDumpToConsole(const sizebuf_t *buf)
Definition common.c:148
void FindFraction(double val, int *num, int *denom, int denomMax)
Definition common.c:1436
static const char base64[]
Definition common.c:1486
cvar_t registered
Definition common.c:32
static const char * hexchar
Definition common.c:81
static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes)
Definition common.c:1487
#define APPEND(ch)
cvar_t cmdline
Definition common.c:33
size_t COM_StringLengthNoColors(const char *s, size_t size_s, qbool *valid)
Definition common.c:1212
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
void COM_Init_Commands(void)
Definition common.c:917
int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix)
Definition common.c:1131
void SZ_Write(sizebuf_t *buf, const unsigned char *data, int length)
Definition common.c:72
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen)
Definition common.c:1502
size_t COM_ToLowerString(const char *in, char *out, size_t size_out)
Returns the number of bytes written to *out excluding the \0 terminator.
Definition common.c:1051
size_t dp__strlcat(char *dst, const char *src, size_t dsize, const char *func, unsigned line)
Catenates a string, like strlcat() but with a better return: the number of bytes copied excluding the...
Definition common.c:1423
#define vsnprintf
Definition common.h:240
int(* COM_LineProcessorFunc)(void *passthrough, const char *line, size_t length, float width, qbool isContination)
Definition common.h:208
float(* COM_WordWidthFunc_t)(void *passthrough, const char *w, size_t *length, float maxWidth)
Definition common.h:207
#define snprintf
Definition common.h:238
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
vector size
vector velocity
vector angles
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
void Cvar_RegisterVirtual(cvar_t *variable, const char *name)
Definition cvar.c:513
#define STRING_COLOR_RGB_TAG_CHAR
Definition draw.h:143
#define STRING_COLOR_TAG
Definition draw.h:140
#define n(x, y)
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLsizei const GLchar ** string
Definition glquake.h:728
GLuint buffer
Definition glquake.h:630
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
GLint GLint GLint GLsizei GLsizei GLenum format
Definition glquake.h:649
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLuint GLuint GLintptr offset
Definition glquake.h:632
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
void Host_Error(const char *error,...)
Definition host.c:85
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition mathlib.c:444
#define min(A, B)
Definition mathlib.h:37
#define DotProduct(a, b)
Definition mathlib.h:98
float strlen(string s)
float fabs(float f)
float floor(float f)
string argv(float n)
static int tokens[VM_TEMPSTRING_MAXSIZE/2]
Definition prvm_cmds.c:2659
prvm_eval_t * src
int i
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define MAX_NUM_ARGVS
Definition qdefs.h:24
#define ISWHITESPACE(ch)
Definition qdefs.h:184
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
bool qbool
Definition qtypes.h:9
Definition cvar.h:66
int integer
Definition cvar.h:73
int argc
Definition sys.h:146
const char ** argv
Definition sys.h:147
static vec3_t forward
Definition sv_user.c:305
static vec3_t right
Definition sv_user.c:305
static vec3_t up
Definition sv_user.c:305
void Sys_Print(const char *text, size_t textlen)
(may) output text to terminal which launched program is POSIX async-signal-safe textlen excludes any ...
Definition sys_shared.c:615
sys_t sys
Definition sys_shared.c:42
Uchar u8_tolower(Uchar ch)
Definition utf8lib.c:2120
cvar_t utf8_enable
Definition utf8lib.c:11
Uchar u8_toupper(Uchar ch)
Definition utf8lib.c:1066
int u8_fromchar(Uchar w, char *to, size_t maxlen)
Encode a wide-character into utf-8.
Definition utf8lib.c:628
Uchar u8_getchar_utf8_enabled(const char *_s, const char **_end)
Fetch a character from an utf-8 encoded string.
Definition utf8lib.c:592
int32_t Uchar
Definition utf8lib.h:35