#include <stdio.h> #include <string> #include <sstream> #include <ctype.h> #include "newprint.h" #include "MudObject.h" #include "colour.h" #include "teleob.h" #include "musicio.h" #include "Player.h" #include "format.h" #include "keys.h" #include "vsprintf.h" #include "misc.h" #include "nations.h" static const int Hex = 1; static const int Octal = 2; static const int Cash = 4; static const int Relative = 8; static const int Long = 16; static const int Compress = 32; static const int Comma = 64; static const int WithId = 128; static const int Capital = 256; static const int ZeroPad = 512; static const int PostPad = 1024; static const int AsChar = 2048; static const int Pronoun = 4096; static string change_article(MudObject *who, MudObject *what, const char *oname, const char *art) { bool worn = what->get_object(KEY_WORNBY)==who; if (worn && strncmp(oname, "a pair of ", 10)==0) { return ssprintf("%s %s", art, oname+10); } if (strncmp(oname, "a ", 2)==0) { return ssprintf("%s %s", art, oname+2); } if (strncmp(oname, "an ", 2)==0) { return ssprintf("%s %s", art, oname+3); } if (strncmp(oname, "some ", 5)==0) { return ssprintf("%s %s", art, oname+5); } return oname; } string printarg_format(const printarg &a, int flags, MudObject *who, const MudObject *&ref, bool &plurref, set<const MudObject*> &mentioned) { if (a.isdefault) return "(blank)"; if (a.isstr) if (a.str) return a.str; else return "(null)"; stringstream s; if (flags & Hex) { s << std::hex; } if (flags & Octal) { s << std::oct; } if (a.isnum) { if (flags & Cash) { return formatcash(a.num, currency(who), 0); } if (flags & AsChar) { char c = a.num; s << c; return s.str(); } s << a.num; return s.str(); } if (a.isreal) { s << a.real; return s.str(); } if (a.isworld) { if (flags & Compress) return magiclist(*a.world, 0, 1); else return magiclist(*a.world, 0, 0); } if (a.isobj || a.istele) { TeleObject o; if (a.istele && a.tele) o = *a.tele; if (a.isobj && a.obj) o = const_cast<MudObject*>(a.obj); if ((flags & (Relative|Pronoun)) && o.what==who) { ref = o; plurref = 1; return "you"; } if (flags & Pronoun) { ref = o; plurref = o->get_flag(FL_PLURAL); return he_or_she(o); } if (!o) { ref = 0; plurref = 0; return "???"; } mentioned.insert(o.what); const char *n = (flags & Long)?name(o):name(o, 0, 0, 1); if (!n) n = o->get("short"); if (!n) n = o->id; if (!n) n = "???"; string blah = ""; if (flags & WithId && o->id) { blah = " ("; blah += o->id; blah += ")"; } ref = o; plurref = ref?o->get_flag(FL_PLURAL):0; if (flags & Relative) { if (o.where==who) return change_article(o.where, o.what, n, "your") + blah; if (is_person(o.where)) { if (mentioned.find(o.where)==mentioned.end()) { string s = name(o.where); s += "'s "; s += remove_articles(n); return s + blah; } else { return change_article(o.where, o.what, n, his_or_her(o.where)) + blah; } } return change_article(who, o.what, n, "the") + blah; } return n + blah; } return "???"; } std::string formatprint(const char *fmt, const PARMS &things) { return formatprint(0, fmt, things); } std::string formatprint(MudObject *who, const char *fmt, const PARMS &things) { string s = ""; size_t i = 0; const MudObject *ref=0; bool plurref=0; set<const MudObject*> mentioned; while (*fmt) { if (*fmt!='%') { s += *fmt; fmt++; continue; } int width = 0, precis = 0; int flags = 0; fmt++; if (*fmt=='%') { s += *fmt; fmt++; continue; } restart: if (*fmt=='[') { int seens = 0; fmt++; while (*fmt && *fmt!=']') { if (*fmt=='/') seens=1; else if (plurref == seens) s += *fmt; fmt++; } fmt++; continue; } if (*fmt=='-') { flags |= PostPad; fmt++; goto restart; } if (*fmt=='0') { flags |= ZeroPad; fmt++; goto restart; } if (*fmt=='#') { flags |= Capital; fmt++; goto restart; } if (*fmt=='(') { flags |= WithId; fmt++; goto restart; } if (*fmt==',') { flags |= Comma; fmt++; goto restart; } if (*fmt=='*') { printarg thing = things[i++]; if (thing.isnum) width = thing.num; if (width > 100) width = 100; fmt++; } if (isdigit(*fmt)) { while (isdigit(*fmt)) { width = width * 10 + *fmt-'0'; fmt++; } goto restart; } if (*fmt=='.') { fmt++; while (isdigit(*fmt)) { precis = precis * 10 + *fmt-'0'; fmt++; } } if (*fmt=='x') { flags |= Hex; } if (*fmt=='o') { flags |= Octal; } if (*fmt=='K') { flags |= Cash; } if (*fmt=='W') { flags |= Compress; } if (*fmt=='P' || *fmt=='Y' || *fmt=='Q') { flags |= Relative; } if (*fmt=='H') { flags |= Pronoun; } if (*fmt=='Q') { flags |= Long; } if (*fmt=='c') { flags |= AsChar; } // NORMAL if (i >= things.size()) { fmt++; continue; } if (*fmt=='f') { printarg thing = things[i++]; if (thing.isreal) { char fmt[1000]; char blah[1000]; sprintf(fmt, "%%%i.%if", width, precis); sprintf(blah, fmt, thing.real); s += blah; } fmt++; continue; } if (*fmt=='|') { printarg thing = things[i++]; if (thing.isobj) { ref = thing.obj; plurref = ref->get_flag(FL_PLURAL); mentioned.insert(ref); } fmt++; continue; } string str = printarg_format(things[i++], flags, who, ref, plurref, mentioned); if (flags & Capital) { if (str[0]=='^' && str.length()>2) str[2] = toupper(str[2]); else if (str.length()>0) str[0] = toupper(str[0]); } if (precis) str = str.substr(0, precis); int dif = width - colour_strnlen(str.c_str(), width, colinfo(who)); while (dif > 0 && !(flags & PostPad)) { s += (flags & ZeroPad)?"0":" "; dif--; } s += str; while (dif > 0 && (flags & PostPad)) { s += " "; dif--; } fmt++; continue; } return s; } printarg::printarg(const OfflinePlayer &p) : isobj(1), obj(p) { }