From bcbb99559a7fb1ee350b45035f7132abb714a59e Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 25 Dec 2009 08:49:38 +0000 Subject: [PATCH] utf8: add VM_sprintf support now sprintf("%#10s", s) pads to 10 bytes, and sprintf("%10s", s) pads to 10 characters, if utf8 is enabled git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9685 d7cf8633-e32d-0410-b094-e92efae38249 --- prvm_cmds.c | 32 +++++++++++++++++++++++++++++--- utf8lib.c | 27 +++++++++++++++++++++++++++ utf8lib.h | 2 ++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/prvm_cmds.c b/prvm_cmds.c index 1e670929..702d8a82 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -5860,7 +5860,8 @@ nolength: if(o < end - 1) { f = &formatbuf[1]; - if(flags & PRINTF_ALTERNATE) *f++ = '#'; + if(*s != 's' && *s != 'c') + if(flags & PRINTF_ALTERNATE) *f++ = '#'; if(flags & PRINTF_ZEROPAD) *f++ = '0'; if(flags & PRINTF_LEFT) *f++ = '-'; if(flags & PRINTF_SPACEPOSITIVE) *f++ = ' '; @@ -5870,19 +5871,44 @@ nolength: *f++ = '*'; *f++ = *s; *f++ = 0; + + if(width < 0) + width = 0; + switch(*s) { case 'd': case 'i': o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg))); break; - case 'o': case 'u': case 'x': case 'X': case 'c': + case 'o': case 'u': case 'x': case 'X': o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg))); break; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': + if(precision < 0) + precision = 6; o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg))); break; + case 'c': + if(precision < 0) + precision = end - o - 1; + if(flags & PRINTF_ALTERNATE) + o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg))); + else + { + unsigned int c = (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)); + const char *buf = u8_encodech(c, NULL); + if(!buf) + buf = ""; + o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision); + } + break; case 's': - o += dpsnprintf(o, end - o, formatbuf, width, precision, GETARG_STRING(thisarg)); + if(precision < 0) + precision = end - o - 1; + if(flags & PRINTF_ALTERNATE) + o += dpsnprintf(o, end - o, formatbuf, width, precision, GETARG_STRING(thisarg)); + else + o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision); break; default: VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0); diff --git a/utf8lib.c b/utf8lib.c index bc3ce39a..b1749c12 100644 --- a/utf8lib.c +++ b/utf8lib.c @@ -694,3 +694,30 @@ u8_COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid) } // never get here } + +/** Pads a utf-8 string + * @param out The target buffer the utf-8 string is written to. + * @param outsize The size of the target buffer, including the final NUL + * @param in The input utf-8 buffer + * @param leftalign Left align the output string (by default right alignment is done) + * @param minwidth The minimum output width + * @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) +{ + if(!utf8_enable.integer) + { + return dpsnprintf(out, outsize, "%*.*s", leftalign ? -(int) minwidth : (int) minwidth, (int) maxwidth, in); + } + else + { + 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 lpad = leftalign ? 0 : pad; + int rpad = leftalign ? pad : 0; + return dpsnprintf(out, outsize, "%*s%.*s%*s", lpad, "", prec, in, rpad, ""); + } +} diff --git a/utf8lib.h b/utf8lib.h index 4c04cfab..f918ed79 100644 --- a/utf8lib.h +++ b/utf8lib.h @@ -44,4 +44,6 @@ size_t u8_COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid // returns a static buffer, use this for inlining char *u8_encodech(Uchar ch, size_t*); +size_t u8_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, size_t minwidth, size_t maxwidth); + #endif // UTF8LIB_H__ -- 2.39.2