size_t qwcslcat (wchar *dst, const wchar *src, size_t size) { size_t dstlen = qwcslen (dst); size_t srclen = qwcslen (src); size_t len = dstlen + srclen; if (len < size) { // it'll fit memcpy (dst + dstlen, src, (srclen + 1) * sizeof(wchar)); return len; } if (dstlen >= size - 1) return srclen + size; if (size == 0) return srclen; assert (size >= 0); // if a negative size was passed, then we're f****d memcpy (dst + dstlen, src, (size - 1 - dstlen)*sizeof(wchar)); dst[size - 1] = 0; return len; }
// disconnect: We assume both str and strSearch are NULL-terminated wchar *qwcsstr (const wchar *str, const wchar *strSearch) { size_t i, j, search; size_t str_len; size_t strSearch_len; str_len = qwcslen (str); strSearch_len = qwcslen (strSearch); search = 0; if (str_len && strSearch_len) { // paranoid check for (i = 0; i < str_len - 1; i++) { // -1 because last wchar is NULL for (j = 0; j < strSearch_len - 1; j++) { // -1 because last wchar is NULL if (str [j + i] != strSearch[j]) { search = 0; break; } else { search = i; } } if (search) break; } } return (wchar *)(str + search); }
wchar *Q_wcsdup (const wchar *src) { wchar *out; size_t size = (qwcslen(src) + 1) * sizeof(wchar); out = Q_malloc (size); memcpy (out, src, size); return out; }
// PLZ free returned string after it no longer need!!! char *wcs2str_malloc (const wchar *ws) { size_t i; size_t len = qwcslen(ws); char *buf = (char *) Q_malloc (len + 1); for (i = 0; i < len; i++) { if (ws[i] == 0) break; buf[i] = ws[i] <= 255 ? (char)ws[i] : '?'; } buf[i] = 0; return buf; }
// NOTE: size is not the number of bytes to copy, but the number of characters. sizeof(dest) / sizeof(wchar) should be used. size_t qwcslcpy (wchar *dst, const wchar *src, size_t size) { size_t len = qwcslen (src); if (len < size) { // it'll fit memmove(dst, src, (len + 1) * sizeof(wchar)); return len; } if (size == 0) return len; assert (size >= 0); // if a negative size was passed, then we're f****d memcpy (dst, src, (size - 1) * sizeof(wchar)); dst[size - 1] = 0; return len; }
// Make sure the renderer can display all Unicode chars in the string, // otherwise try to replace them with Latin equivalents wchar *maybe_transliterate (wchar *src) { wchar *dst, *trans; static wchar buf[2048]; #define buflen (sizeof(buf)/sizeof(buf[0])) int len; dst = buf; while (*src && dst < buf+buflen-1) { if (R_CharAvailable(*src)) *dst++ = *src; else { trans = transliterate_char (*src); len = min(qwcslen(trans), buf+buflen-1 - dst); memcpy (dst, trans, len*sizeof(wchar)); dst += len; } src++; } *dst = 0; return buf; }
wchar *decode_string (const char *s) { static wchar buf[2048]; // should be enough for everyone!!! char encoding[13]; char enc_str[1024]; const char *p, *q, *r; wchar *decoded; int i; buf[0] = 0; p = s; while (1) { p = strstr(p, "=`"); if (!p) break; // copy source string up to p as is qwcslcat (buf, str2wcs(s), min(p-s+qwcslen(buf)+1, sizeof(buf)/sizeof(buf[0]))); s = p; p += 2; // skip the =` for (q = p; isalnum(*q) && q - p < 12; q++) { ; } if (!*q) break; if (*q != ':') { p += 2; continue; } q++; // skip the : assert (q - p <= sizeof(encoding)); strlcpy (encoding, p, q - p); r = strstr(q, "`="); if (!r) { p = q; continue; } strlcpy (enc_str, q, min(r - q + 1, sizeof(enc_str))); for (i = 0; decode_table[i].name; i++) { if (!strcasecmp(encoding, decode_table[i].name)) break; // found it } if (!decode_table[i].name) { // unknown encoding p = r + 2; continue; } decoded = decode_table[i].func(enc_str); qwcslcat (buf, decoded, sizeof(buf)/sizeof(buf[0])); Q_free (decoded); s = p = r + 2; } // copy remainder as is qwcslcat (buf, str2wcs(s), sizeof(buf)/sizeof(buf[0])); return maybe_transliterate(buf); }