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++ = ' ';
*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);
}
// 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, "");
+ }
+}