]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - utf8lib.c
Now with new Travis secret key.
[xonotic/darkplaces.git] / utf8lib.c
index b726e220d9768ca01d82b973aba0d5d464fecdd2..155b4aea9a8f949ecf8e2a583487c4fa122896cc 100644 (file)
--- 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])
@@ -596,15 +694,14 @@ int u8_fromchar(Uchar w, char *to, size_t maxlen)
  * @param l         The number of bytes without the terminating null.
  * @return          A statically allocated buffer containing the character's utf8 representation, or NULL if it fails.
  */
-char *u8_encodech(Uchar ch, size_t *l)
+char *u8_encodech(Uchar ch, size_t *l, char *buf16)
 {
-       static char buf[16];
        size_t len;
-       len = u8_fromchar(ch, buf, sizeof(buf));
+       len = u8_fromchar(ch, buf16, 16);
        if (len > 0)
        {
                if (l) *l = len;
-               return buf;
+               return buf16;
        }
        return NULL;
 }
@@ -675,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;
@@ -695,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;
@@ -715,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;
@@ -753,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;
                }
 
@@ -761,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;
                }
 
@@ -781,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)
        {
@@ -791,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