ledger/format.cc
2004-07-26 23:33:51 -04:00

195 lines
3.8 KiB
C++

#include "format.h"
namespace ledger {
std::string truncated(const std::string& str, unsigned int width)
{
char buf[256];
std::memset(buf, '\0', 255);
assert(width < 256);
std::strncpy(buf, str.c_str(), str.length());
if (buf[width])
std::strcpy(&buf[width - 2], "..");
return buf;
}
std::string maximal_account_name(const item_t * item,
const item_t * parent)
{
std::string name = item->account->name;
for (const item_t * i = item->parent;
i && i->account && i != parent;
i = i->parent)
name = i->account->name + ":" + name;
return name;
}
std::string format_string(const item_t * item, const format_t& format,
const item_t * displayed_parent)
{
std::string result;
for (const char * p = format.format_string.c_str(); *p; p++) {
if (*p == '%') {
bool leftalign = false;
bool ignore = false;
int width = 0;
int strict_width = 0;
++p;
if (*p == '?') {
ignore = false; //subsequent_line;
++p;
}
if (*p == '-') {
leftalign = true;
++p;
}
std::string num;
while (*p && std::isdigit(*p))
num += *p++;
if (! num.empty())
width = std::atol(num.c_str());
if (*p == '.') {
++p;
num = "";
while (*p && std::isdigit(*p))
num += *p++;
if (! num.empty()) {
strict_width = std::atol(num.c_str());
if (width == 0)
width = strict_width;
}
}
std::ostringstream out;
if (leftalign)
out << std::left;
else
out << std::right;
if (width > 0)
out.width(width);
if (ignore) {
out << " ";
result += out.str();
continue;
}
switch (*p) {
case '%':
out << "%";
break;
case '(': {
++p;
num = "";
while (*p && *p != ')')
num += *p++;
assert(*p == ')');
node_t * style = parse_expr(num, NULL);
balance_t value = style->compute(format.begin(), format.end(), item);
value.write(out, width, strict_width > 0 ? strict_width : width);
break;
}
case '[': {
++p;
num = "";
while (*p && *p != ']')
num += *p++;
assert(*p == ']');
if (item->date != -1) {
char buf[256];
std::strftime(buf, 255, num.c_str(), std::gmtime(&item->date));
out << (strict_width == 0 ? buf : truncated(buf, strict_width));
} else {
out << " ";
}
break;
}
case 'd': {
if (item->date != -1) {
char buf[32];
std::strftime(buf, 31, "%Y/%m/%d", std::gmtime(&item->date));
out << (strict_width == 0 ? buf : truncated(buf, strict_width));
} else {
out << " ";
}
break;
}
case 'p':
out << (strict_width == 0 ?
item->payee : truncated(item->payee, strict_width));
break;
case 'n':
if (item->account) {
std::string name = maximal_account_name(item, displayed_parent);
out << (strict_width == 0 ? name : truncated(name, strict_width));
} else {
out << " ";
}
break;
case 'N':
if (item->account)
out << (strict_width == 0 ?
item->account->fullname() :
truncated(item->account->fullname(), strict_width));
else
out << " ";
break;
case 't':
if (format.value_style) {
balance_t value = format.compute_value(item);
value.write(out, width, strict_width > 0 ? strict_width : width);
}
break;
case 'T':
if (format.total_style) {
balance_t value = format.compute_total(item);
value.write(out, width, strict_width > 0 ? strict_width : width);
}
break;
case '_': {
int depth = 0;
for (const item_t * i = item; i->parent; i = i->parent)
depth++;
for (const item_t * i = item->parent;
i && i->account && i != displayed_parent;
i = i->parent)
depth--;
while (--depth >= 0) {
if (width > 0 || strict_width > 0)
out.width(width > strict_width ? width : strict_width);
out << " ";
}
break;
}
}
result += out.str();
} else {
result += *p;
}
}
return result;
}
} // namespace ledger