musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
#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) {
}