Skip to content

Commit b371d47

Browse files
committed
Fix filtertext, logging and escape/unescape
Treat '\r' like a newline and display tabs as single spaces
1 parent 1ecd08d commit b371d47

6 files changed

Lines changed: 83 additions & 65 deletions

File tree

source/engine/command.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -925,22 +925,34 @@ const char *parsestring(const char *p)
925925
int unescapestring(char *dst, const char *src, const char *end)
926926
{
927927
char *start = dst;
928-
while(src < end)
928+
uint c;
929+
uint s = uni_getchar(src, c);
930+
for(char *p = (char *)src; src < end; p += s, s = uni_getchar(p, c))
929931
{
930-
int c = *src++;
932+
if(iscubecntrl(c) || c == 0xFFFD)
933+
{
934+
src += s;
935+
continue;
936+
}
931937
if(c == '^')
932938
{
933-
if(src >= end) break;
934-
int e = *src++;
935-
switch(e)
939+
if(src+1 >= end) break;
940+
switch(*(src+1))
936941
{
937-
case 'n': *dst++ = '\n'; break;
938-
case 't': *dst++ = '\t'; break;
939-
case 'f': *dst++ = '\f'; break;
940-
default: *dst++ = e; break;
942+
case 'n': *dst++ = '\n'; ++src; ++p; break;
943+
case 'r': *dst++ = '\r'; ++src; ++p; break;
944+
case 't': *dst++ = '\t'; ++src; ++p; break;
945+
case 'f': *dst++ = '\f'; ++src; ++p; break;
946+
case '^': *dst++ = '^' ; ++src; ++p; break;
947+
default: break;
941948
}
949+
++src;
950+
}
951+
else
952+
{
953+
loopi(s) *dst++ = p[i];
954+
src += s;
942955
}
943-
else *dst++ = c;
944956
}
945957
*dst = '\0';
946958
return dst - start;
@@ -3162,21 +3174,29 @@ bool execfile(const char *cfgfile, bool msg)
31623174
}
31633175
ICOMMAND(exec, "sb", (char *file, int *msg), intret(execfile(file, *msg != 0) ? 1 : 0));
31643176

3165-
const char *escapestring(const char *s)
3177+
const char *escapestring(const char *str)
31663178
{
31673179
stridx = (stridx + 1)%4;
31683180
vector<char> &buf = strbuf[stridx];
31693181
buf.setsize(0);
31703182
buf.add('"');
3171-
for(; *s; s++) switch(*s)
3183+
uint c;
3184+
uint s = uni_getchar(str, c);
3185+
for(char *p = (char *)str; c; p += s, s = uni_getchar(p, c)) switch(c)
31723186
{
31733187
case '\n': buf.put("^n", 2); break;
3188+
case '\r': buf.put("^r", 2); break;
31743189
case '\t': buf.put("^t", 2); break;
31753190
case '\f': buf.put("^f", 2); break;
31763191
case '"': buf.put("^\"", 2); break;
31773192
case '^': buf.put("^^", 2); break;
3178-
default: buf.add(*s); break;
3193+
default:
3194+
{
3195+
if(iscubecntrl(c) || c == 0xFFFD) break; // filter out control characters
3196+
buf.put(p, s); break;
3197+
}
31793198
}
3199+
31803200
buf.put("\"\0", 2);
31813201
return buf.getbuf();
31823202
}

source/engine/rendertext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ static inline SDL_Surface *fetch_glyph(uint codepoint)
392392
if(g->surf) return g->surf;
393393

394394
// draw the character in white, or the replacement character (0xFFFD) if the requested glyph is not available
395-
SDL_Surface *surf = TTF_RenderGlyph32_Blended(curfont->face->face, codepoint, {255, 255, 255});
395+
SDL_Surface *surf = TTF_RenderGlyph32_Blended(curfont->face->face, codepoint == '\t' ? ' ' : codepoint, {255, 255, 255});
396396
if(!surf) surf = TTF_RenderGlyph32_Blended(curfont->face->face, 0xFFFD, {255, 255, 255});
397397
if(!surf) return NULL;
398398

source/engine/server.cpp

Lines changed: 11 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,13 @@ void logoutf(const char *fmt, ...)
4545
va_end(args);
4646
}
4747

48-
static void writelog(FILE *file, const char *buf_)
48+
static void writelog(FILE *file, const char *buf)
4949
{
50-
const uchar *buf = (const uchar *)buf_;
51-
static uchar ubuf[512];
52-
size_t len = strlen(buf_);
53-
int j = 0;
54-
loopi(min(size_t(512), len))
55-
{
56-
// strip colors and control codes
57-
if(buf[i] <= 0x09 || buf[i] == 0x0B || buf[i] == 0x0C || (buf[i] >= 0x0E && buf[i] <= 0x1F) || buf[i] == 0x7F)
58-
{
59-
if(buf[i] == '\f') ++i;
60-
continue;
61-
}
62-
if(buf[i] == 0xC2 && buf[i+1] >= 0x80 && buf[i+1] <= 0x9F) // control codes: U+80 - U+9F
63-
{
64-
++i;
65-
continue;
66-
}
67-
ubuf[j++] = buf[i];
68-
}
69-
ubuf[j++] = '\n';
70-
fwrite(ubuf, 1, min(512, j), file);
50+
static char ubuf[512];
51+
filteruni(ubuf, buf, 511);
52+
const size_t len = min((size_t)511, strlen(ubuf));
53+
ubuf[len] = '\n';
54+
fwrite(ubuf, 1, len+1, file);
7155
}
7256

7357
static void writelogv(FILE *file, const char *fmt, va_list args)
@@ -822,28 +806,11 @@ static BOOL WINAPI consolehandler(DWORD dwCtrlType)
822806

823807
static void writeline(logline &line)
824808
{
825-
static uchar buf[512];
826-
size_t len = strlen(line.buf);
827-
int j = 0;
828-
loopi(min(size_t(512-1), len))
829-
{
830-
// strip colors and control codes
831-
if(buf[i] <= 0x09 || buf[i] == 0x0B || buf[i] == 0x0C || (buf[i] >= 0x0E && buf[i] <= 0x1F) || buf[i] == 0x7F)
832-
{
833-
if(buf[i] == '\f') ++i;
834-
continue;
835-
}
836-
if(buf[i] == 0xC2 && buf[i+1] >= 0x80 && buf[i+1] <= 0x9F) // control codes: U+80 - U+9F
837-
{
838-
++i;
839-
continue;
840-
}
841-
ubuf[j++] = buf[i];
842-
}
843-
ubuf[j++] = '\r';
844-
ubuf[j++] = '\n';
845-
DWORD written = 0;
846-
WriteConsole(outhandle, ubuf, j, &written, NULL);
809+
static char ubuf[512];
810+
filteruni(ubuf, line.buf, 511);
811+
const size_t len = min((size_t)511, strlen(ubuf));
812+
DWORD written;
813+
WriteConsole(outhandle, ubuf, len, &written, NULL);
847814
}
848815

849816
static void setupconsole()

source/shared/tools.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,30 +196,58 @@ void getstring(char *text, ucharbuf &p, size_t len)
196196
void filtertext(char *dst, const char *src, uint flags, size_t len, int unilen)
197197
{
198198
uint c;
199-
uint s = uni_getchar(src, c);
199+
size_t s = uni_getchar(src, c);
200200
for(char *p = (char *)src; c; p += s, s = uni_getchar(p, c))
201201
{
202-
if((!(flags&T_COLORS) && c == '\f') || (!(flags&T_NEWLINES) && c == '\n'))
202+
if(!(flags&T_COLORS) && c == '\f')
203203
{
204-
if(!*++p) break;
204+
if(!*(++p)) break;
205205
continue;
206206
}
207-
if(!(flags&T_NAME ? iscubenamesafe(c) : iscubeprint(c)))
207+
if(!(flags&T_NEWLINES) && (c == '\n' || c == '\r'))
208+
{
209+
if(!*(p+1)) break;
210+
continue;
211+
}
212+
if(!((flags&T_NAME) ? iscubenamesafe(c) : iscubeprint(c)) && c != '\f' && c != '\n' && c != '\r')
208213
{
209214
if(!iscubespace(c) || !(flags&T_WHITESPACE)) continue;
210215
if(flags&T_FORCESPACE)
211216
{
212217
*dst++ = ' ';
218+
len--;
219+
unilen--;
213220
continue;
214221
}
215222
}
223+
s = min(s, len); // prevent overflow
216224
loopi(s) *dst++ = p[i];
217-
if(s <= len) len -= s; else len = 0;
225+
len -= s;
218226
unilen--;
219227
if(!len || !unilen) break;
220228
}
221229
*dst = '\0';
222230
}
231+
// like `filtertext` but only strips colors and control characters, used for logs
232+
void filteruni(char *dst, const char *src, size_t len)
233+
{
234+
uint c;
235+
size_t s = uni_getchar(src, c);
236+
for(char *p = (char *)src; c; p += s, s = uni_getchar(p, c))
237+
{
238+
if(c == '\f')
239+
{
240+
if(!*(++p)) break;
241+
continue;
242+
}
243+
if(iscubecntrl(c) || c == 0xFFFD) continue;
244+
s = min(s, len); // prevent overflow
245+
loopi(s) *dst++ = p[i];
246+
len -= s;
247+
if(!len) break;
248+
}
249+
*dst = '\0';
250+
}
223251

224252
void ipmask::parse(const char *name)
225253
{

source/shared/tools.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1390,11 +1390,12 @@ static inline int iscubeprint(uint c)
13901390
|| (c >= 0x20A0 && c <= 0x20C0) // Currency Symbols [33]
13911391
;
13921392
}
1393-
static inline int iscubespace(uint c) { return (c >= 0x09 && c <= 0x0D) || c == ' ' ? 1 : 0; }
1393+
static inline int iscubespace(uint c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' ? 1 : 0; }
13941394
static inline int iscubealpha(uint c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ? 1 : 0; }
13951395
static inline int iscubealnum(uint c) { return (c >= '0' && c <= '9') || iscubealpha(c) ? 1 : 0; }
13961396
static inline int iscubelower(uint c) { return (c >= 'a' && c <= 'z') ? 1 : 0; }
13971397
static inline int iscubeupper(uint c) { return (c >= 'A' && c <= 'Z') ? 1 : 0; }
1398+
static inline int iscubecntrl(uint c) { return c <= 0x1F || (c >= 0x7F && c <= 0x9F) ? 1 : 0; }
13981399
static inline int iscubepunct(uint c) { return (c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') ? 1 : 0; }
13991400
// a subeset of console characters that are allowed in player names
14001401
// the default font should contain glyphs for all of these
@@ -1471,6 +1472,8 @@ extern void getstring(char *t, ucharbuf &p, size_t len);
14711472
template<size_t N> static inline void getstring(char (&t)[N], ucharbuf &p) { getstring(t, p, N); }
14721473
extern void filtertext(char *dst, const char *src, uint flags, size_t len, int unilen = -1);
14731474
template<size_t N> static inline void filtertext(char (&dst)[N], const char *src, uint flags) { filtertext(dst, src, flags, N-1, N-1); }
1475+
extern void filteruni(char *dst, const char *src, size_t len);
1476+
template<size_t N> static inline void filteruni(char (&dst)[N], const char *src) { filteruni(dst, src, N-1); }
14741477

14751478
struct ipmask
14761479
{

source/shared/unicode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ static inline int uni_getchar(const char *str, uint &codepoint)
2626
if(p[0] >> 3 == 0x1E && p[1] >> 6 == 0x02 && p[2] >> 6 == 0x02 && p[3] >> 6 == 0x02)
2727
{
2828
codepoint = ((p[0] & 0x07) << 18) | ((p[1] & 0x3F) << 12) | ((p[2] & 0x3F) << 6) | (p[3] & 0x3F);
29-
if(codepoint < 0x10000) codepoint = 0xFFFD;
29+
if(codepoint < 0x10000 || codepoint > 0x10FFFF) codepoint = 0xFFFD;
3030
return 4;
3131
}
3232
codepoint = 0xFFFD;

0 commit comments

Comments
 (0)