X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=utf8lib.c;h=155b4aea9a8f949ecf8e2a583487c4fa122896cc;hp=8994bd7a00a697e124779b86318919aea0d5aaf9;hb=6ff5802848663ece807c1a425da91d7630a8a036;hpb=cfee52a1ec9db338098789cae89ae5cf1f7a6fbf diff --git a/utf8lib.c b/utf8lib.c index 8994bd7a..155b4aea 100644 --- a/utf8lib.c +++ b/utf8lib.c @@ -1,5 +1,6 @@ -#include "quakedef.h" +#include "darkplaces.h" #include "utf8lib.h" +#include "draw.h" /* ================================================================================ @@ -7,7 +8,7 @@ Initialization of UTF-8 support and new cvars. ================================================================================ */ // for compatibility this defaults to 0 -cvar_t utf8_enable = {CVAR_SAVE, "utf8_enable", "0", "Enable UTF-8 support. For compatibility, this is disabled by default in most games."}; +cvar_t utf8_enable = {CF_CLIENT | CF_SERVER | CF_ARCHIVE, "utf8_enable", "0", "Enable UTF-8 support. For compatibility, this is disabled by default in most games."}; void u8_Init(void) { @@ -59,7 +60,7 @@ Uchar utf8_range[5] = { * @return Whether or not another valid character is in the string */ #define U8_ANALYZE_INFINITY 7 -static qboolean u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch, size_t _maxlen) +static qbool u8_analyze(const char *_s, size_t *_start, size_t *_len, Uchar *_ch, size_t _maxlen) { const unsigned char *s = (const unsigned char*)_s; size_t i, j; @@ -226,6 +227,20 @@ size_t u8_strlen(const char *_s) return len; } +static int colorcode_skipwidth(const unsigned char *s) +{ + if(*s == STRING_COLOR_TAG) + { + if(s[1] <= '9' && s[1] >= '0') // ^[0-9] found + return 2; + else if(s[1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4])) + return 5; + else if(s[1] == STRING_COLOR_TAG) + return 1; // special case, do NOT call colorcode_skipwidth for next char + } + return 0; +} + /** Get the number of characters in a part of an UTF-8 string. * @param _s An utf-8 encoded null-terminated string. * @param n The maximum number of bytes. @@ -274,6 +289,49 @@ size_t u8_strnlen(const char *_s, size_t n) return len; } +static size_t u8_strnlen_colorcodes(const char *_s, size_t n) +{ + size_t st, ln; + size_t len = 0; + const unsigned char *s = (const unsigned char*)_s; + + while (*s && n) + { + int w = colorcode_skipwidth(s); + n -= w; + s += w; + if(w > 1) // == 1 means single caret + continue; + + // ascii char, skip u8_analyze + if (*s < 0x80 || !utf8_enable.integer) + { + ++len; + ++s; + --n; + continue; + } + + // invalid, skip u8_analyze + if (*s < 0xC2) + { + ++s; + --n; + continue; + } + + if (!u8_analyze((const char*)s, &st, &ln, NULL, n)) + break; + // valid character, see if it's still inside the range specified by n: + if (n < st + ln) + return len; + ++len; + n -= st + ln; + s += st + ln; + } + return len; +} + /** Get the number of bytes used in a string to represent an amount of characters. * @param _s An utf-8 encoded null-terminated string. * @param n The number of characters we want to know the byte-size for. @@ -318,6 +376,46 @@ size_t u8_bytelen(const char *_s, size_t n) return len; } +static size_t u8_bytelen_colorcodes(const char *_s, size_t n) +{ + size_t st, ln; + size_t len = 0; + const unsigned char *s = (const unsigned char*)_s; + + while (*s && n) + { + int w = colorcode_skipwidth(s); + len += w; + s += w; + if(w > 1) // == 1 means single caret + continue; + + // ascii char, skip u8_analyze + if (*s < 0x80 || !utf8_enable.integer) + { + ++len; + ++s; + --n; + continue; + } + + // invalid, skip u8_analyze + if (*s < 0xC2) + { + ++s; + ++len; + continue; + } + + if (!u8_analyze((const char*)s, &st, &ln, NULL, U8_ANALYZE_INFINITY)) + break; + --n; + s += st + ln; + len += st + ln; + } + return len; +} + /** Get the byte-index for a character-index. * @param _s An utf-8 encoded string. * @param i The character-index for which you want the byte offset. @@ -339,7 +437,7 @@ int u8_byteofs(const char *_s, size_t i, size_t *len) } if (len) *len = 1; - return i; + return (int)i; } st = ln = 0; @@ -352,7 +450,7 @@ int u8_byteofs(const char *_s, size_t i, size_t *len) } while(i-- > 0); if (len) *len = ln; - return ofs; + return (int)ofs; } /** Get the char-index for a byte-index. @@ -372,7 +470,7 @@ int u8_charidx(const char *_s, size_t i, size_t *len) if (!utf8_enable.integer) { if (len) *len = 0; - return i; + return (int)i; } while (ofs < i && s[ofs]) @@ -674,9 +772,9 @@ all characters until the zero terminator. ============ */ size_t -COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid); +COM_StringLengthNoColors(const char *s, size_t size_s, qbool *valid); size_t -u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) +u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qbool *valid) { const unsigned char *s = (const unsigned char*)_s; const unsigned char *end; @@ -694,7 +792,7 @@ u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) { case 0: if(valid) - *valid = TRUE; + *valid = true; return len; case STRING_COLOR_TAG: ++s; @@ -714,7 +812,7 @@ u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) case 0: // ends with unfinished color code! ++len; if(valid) - *valid = FALSE; + *valid = false; return len; case STRING_COLOR_TAG: // escaped ^ ++len; @@ -752,7 +850,7 @@ u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) { // we CAN end up here, if an invalid char is between this one and the end of the string if(valid) - *valid = TRUE; + *valid = true; return len; } @@ -760,7 +858,7 @@ u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) { // string length exceeded by new character if(valid) - *valid = TRUE; + *valid = true; return len; } @@ -780,7 +878,7 @@ u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qboolean *valid) * @param maxwidth The maximum output width * @return The number of bytes written, not including the terminating \0 */ -size_t u8_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, size_t minwidth, size_t maxwidth) +size_t u8_strpad(char *out, size_t outsize, const char *in, qbool leftalign, size_t minwidth, size_t maxwidth) { if(!utf8_enable.integer) { @@ -790,14 +888,25 @@ size_t u8_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, { size_t l = u8_bytelen(in, maxwidth); size_t actual_width = u8_strnlen(in, l); - int pad = (actual_width >= minwidth) ? 0 : (minwidth - actual_width); - int prec = l; + int pad = (int)((actual_width >= minwidth) ? 0 : (minwidth - actual_width)); + int prec = (int)l; int lpad = leftalign ? 0 : pad; int rpad = leftalign ? pad : 0; return dpsnprintf(out, outsize, "%*s%.*s%*s", lpad, "", prec, in, rpad, ""); } } +size_t u8_strpad_colorcodes(char *out, size_t outsize, const char *in, qbool leftalign, size_t minwidth, size_t maxwidth) +{ + size_t l = u8_bytelen_colorcodes(in, maxwidth); + size_t actual_width = u8_strnlen_colorcodes(in, l); + int pad = (int)((actual_width >= minwidth) ? 0 : (minwidth - actual_width)); + int prec = (int)l; + int lpad = leftalign ? 0 : pad; + int rpad = leftalign ? pad : 0; + return dpsnprintf(out, outsize, "%*s%.*s%*s", lpad, "", prec, in, rpad, ""); +} + /* The two following functions (u8_toupper, u8_tolower) are derived from