package dk.socketmud.util; public class Format { private static final String AnsiCodes = "unrRgGpPcCdDwWbByY"; private static final String ReplaceCodes = "#"; public static String cprintf(String fmt, Object ... varargs) { return cprintf(fmt.toCharArray(), varargs); } public static String cprintf(char[] fmt, Object ... varargs) { StringBuffer buf = new StringBuffer(); int i = 0; int len = fmt.length; int argc = 0; while (i < len) { boolean reverse = false; int size = 0; int maxSize = 0; switch (fmt[i]) { default: buf.append(fmt[i++]); break; case '%': // should we align this in reverse? if (fmt[i + 1] == '-') { i++; reverse = true; } // get the size, if any while (Character.isDigit(fmt[i + 1])) { i++; size *= 10; size += fmt[i] - '0'; } // any size restrictions? if (fmt[i + 1] == '.') { i++; while (Character.isDigit(fmt[i + 1])) { i++; maxSize *= 10; maxSize += fmt[i] - '0'; } } i++; switch (fmt[i]) { default: buf.append('%'); break; case 's': String s = (String) getVarArg(fmt[i], argc, varargs); if (maxSize > 0) s = restrictString(s, maxSize); size -= colourLength(s); argc++; if (!reverse) { while(size-- > 0) buf.append(' '); } buf.append(s); if (reverse) { while(size-- > 0) buf.append(' '); } i++; break; case 'd': int value = (Integer) getVarArg(fmt[i], argc, varargs); argc++; // a little trick to see how long the number is String tmp = "" + value; size -= tmp.length(); if (!reverse) { while(size-- > 0) buf.append(' '); } buf.append(tmp); if (reverse) { while(size-- > 0) buf.append(' '); } i++; break; } break; } } return buf.toString(); } private static Object getVarArg(char type, int num, Object ... varargs) throws IllegalArgumentException { if (varargs.length < (num + 1)) throw new IllegalArgumentException("Not enough variable arguments"); Object o = varargs[num]; switch (type) { default: throw new IllegalArgumentException("Unknown type '" + type + "'"); case 's': if (o instanceof String) break; else throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type String"); case 'd': if (o instanceof Integer) break; else throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type Integer"); } return o; } public static String restrictString(String s, int maxSize) { StringBuffer buf = new StringBuffer(); char[] c = s.toCharArray(); boolean done = false; int size = s.length(); int len = 0; int i = 0; while (i < size && !done) { boolean found = false; switch (c[i]) { default: if (++len > maxSize) { done = true; break; } buf.append(c[i]); i++; break; case '#': i++; if (AnsiCodes.indexOf(c[i]) > -1) { buf.append('#'); buf.append(c[i]); i++; found = true; } if (!found && ReplaceCodes.indexOf(c[i]) > - 1) { if (++len > maxSize) { done = true; break; } buf.append('#'); buf.append(c[i]); found = true; } if (!found) { if (++len > maxSize) { done = true; break; } buf.append('#'); } break; } } return buf.toString(); } private static int colourLength(String s) { char[] c = s.toCharArray(); int len = 0; int max = s.length(); int i = 0; while (i < max) { boolean found = false; switch(c[i]) { default: len++; i++; break; case '#': i++; if (AnsiCodes.indexOf(c[i]) > -1) { i++; found = true; } if (!found && ReplaceCodes.indexOf(c[i]) > - 1) { len++; i++; found = true; } if (!found) len++; break; } } return len; } }