OSDN Git Service

Added columns 'completedeffort' and 'remainingeffort' to reports.
[tjqt4port/tj2qt4.git] / taskjuggler / HTMLReportElement.cpp
index 8506633..e247ea4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Report.cpp - TaskJuggler
+ * HTMLReportElement.cpp - TaskJuggler
  *
- * Copyright (c) 2001, 2002, 2003 by Chris Schlaeger <cs@suse.de>
+ * Copyright (c) 2001, 2002, 2003, 2004, 2005 by Chris Schlaeger <cs@kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
  * $Id$
  */
 
-#include <config.h>
+#include "HTMLReportElement.h"
+
+#include <assert.h>
 
 #include "TjMessageHandler.h"
 #include "tjlib-internal.h"
 #include "Project.h"
 #include "Resource.h"
-#include "Report.h"
-#include "Booking.h"
+#include "Account.h"
 #include "BookingList.h"
 #include "Utility.h"
 #include "MacroTable.h"
+#include "TableLineInfo.h"
+#include "TableCellInfo.h"
+#include "ReferenceAttribute.h"
+#include "TextAttribute.h"
+#include "HTMLReport.h"
+#include "UsageLimits.h"
+
+HTMLReportElement::HTMLReportElement(Report* r, const QString& df, int dl) :
+    ReportElement(r, df, dl),
+    HTMLPrimitives()
+{
+}
 
-#define KW(a) a
-
-/* The following encoding table was copied from the Qt library sources since
- * this information is not available over the public API. */
-
-struct Entity 
-{
-       const char * name;
-       Q_UINT16 code;
-};
-
-static const Entity entitylist [] = 
-{
-    { "AElig", 0x00c6 },
-    { "Aacute", 0x00c1 },
-    { "Acirc", 0x00c2 },
-    { "Agrave", 0x00c0 },
-    { "Alpha", 0x0391 },
-    { "AMP", 38 },
-    { "Aring", 0x00c5 },
-    { "Atilde", 0x00c3 },
-    { "Auml", 0x00c4 },
-    { "Beta", 0x0392 },
-    { "Ccedil", 0x00c7 },
-    { "Chi", 0x03a7 },
-    { "Dagger", 0x2021 },
-    { "Delta", 0x0394 },
-    { "ETH", 0x00d0 },
-    { "Eacute", 0x00c9 },
-    { "Ecirc", 0x00ca },
-    { "Egrave", 0x00c8 },
-    { "Epsilon", 0x0395 },
-    { "Eta", 0x0397 },
-    { "Euml", 0x00cb },
-    { "Gamma", 0x0393 },
-    { "GT", 62 },
-    { "Iacute", 0x00cd },
-    { "Icirc", 0x00ce },
-    { "Igrave", 0x00cc },
-    { "Iota", 0x0399 },
-    { "Iuml", 0x00cf },
-    { "Kappa", 0x039a },
-    { "Lambda", 0x039b },
-    { "LT", 60 },
-    { "Mu", 0x039c },
-    { "Ntilde", 0x00d1 },
-    { "Nu", 0x039d },
-    { "OElig", 0x0152 },
-    { "Oacute", 0x00d3 },
-    { "Ocirc", 0x00d4 },
-    { "Ograve", 0x00d2 },
-    { "Omega", 0x03a9 },
-    { "Omicron", 0x039f },
-    { "Oslash", 0x00d8 },
-    { "Otilde", 0x00d5 },
-    { "Ouml", 0x00d6 },
-    { "Phi", 0x03a6 },
-    { "Pi", 0x03a0 },
-    { "Prime", 0x2033 },
-    { "Psi", 0x03a8 },
-    { "QUOT", 34 },
-    { "Rho", 0x03a1 },
-    { "Scaron", 0x0160 },
-    { "Sigma", 0x03a3 },
-    { "THORN", 0x00de },
-    { "Tau", 0x03a4 },
-    { "Theta", 0x0398 },
-    { "Uacute", 0x00da },
-    { "Ucirc", 0x00db },
-    { "Ugrave", 0x00d9 },
-    { "Upsilon", 0x03a5 },
-    { "Uuml", 0x00dc },
-    { "Xi", 0x039e },
-    { "Yacute", 0x00dd },
-    { "Yuml", 0x0178 },
-    { "Zeta", 0x0396 },
-    { "aacute", 0x00e1 },
-    { "acirc", 0x00e2 },
-    { "acute", 0x00b4 },
-    { "aelig", 0x00e6 },
-    { "agrave", 0x00e0 },
-    { "alefsym", 0x2135 },
-    { "alpha", 0x03b1 },
-    { "amp", 38 },
-    { "and", 0x22a5 },
-    { "ang", 0x2220 },
-    { "apos", 0x0027 },
-    { "aring", 0x00e5 },
-    { "asymp", 0x2248 },
-    { "atilde", 0x00e3 },
-    { "auml", 0x00e4 },
-    { "bdquo", 0x201e },
-    { "beta", 0x03b2 },
-    { "brvbar", 0x00a6 },
-    { "bull", 0x2022 },
-    { "cap", 0x2229 },
-    { "ccedil", 0x00e7 },
-    { "cedil", 0x00b8 },
-    { "cent", 0x00a2 },
-    { "chi", 0x03c7 },
-    { "circ", 0x02c6 },
-    { "clubs", 0x2663 },
-    { "cong", 0x2245 },
-    { "copy", 0x00a9 },
-    { "crarr", 0x21b5 },
-    { "cup", 0x222a },
-    { "curren", 0x00a4 },
-    { "dArr", 0x21d3 },
-    { "dagger", 0x2020 },
-    { "darr", 0x2193 },
-    { "deg", 0x00b0 },
-    { "delta", 0x03b4 },
-    { "diams", 0x2666 },
-    { "divide", 0x00f7 },
-    { "eacute", 0x00e9 },
-    { "ecirc", 0x00ea },
-    { "egrave", 0x00e8 },
-    { "empty", 0x2205 },
-    { "emsp", 0x2003 },
-    { "ensp", 0x2002 },
-    { "epsilon", 0x03b5 },
-    { "equiv", 0x2261 },
-    { "eta", 0x03b7 },
-    { "eth", 0x00f0 },
-    { "euml", 0x00eb },
-    { "euro", 0x20ac },
-    { "exist", 0x2203 },
-    { "fnof", 0x0192 },
-    { "forall", 0x2200 },
-    { "frac12", 0x00bd },
-    { "frac14", 0x00bc },
-    { "frac34", 0x00be },
-    { "frasl", 0x2044 },
-    { "gamma", 0x03b3 },
-    { "ge", 0x2265 },
-    { "gt", 62 },
-    { "hArr", 0x21d4 },
-    { "harr", 0x2194 },
-    { "hearts", 0x2665 },
-    { "hellip", 0x2026 },
-    { "iacute", 0x00ed },
-    { "icirc", 0x00ee },
-    { "iexcl", 0x00a1 },
-    { "igrave", 0x00ec },
-    { "image", 0x2111 },
-    { "infin", 0x221e },
-    { "int", 0x222b },
-    { "iota", 0x03b9 },
-    { "iquest", 0x00bf },
-    { "isin", 0x2208 },
-    { "iuml", 0x00ef },
-    { "kappa", 0x03ba },
-    { "lArr", 0x21d0 },
-    { "lambda", 0x03bb },
-    { "lang", 0x2329 },
-    { "laquo", 0x00ab },
-    { "larr", 0x2190 },
-    { "lceil", 0x2308 },
-    { "ldquo", 0x201c },
-    { "le", 0x2264 },
-    { "lfloor", 0x230a },
-    { "lowast", 0x2217 },
-    { "loz", 0x25ca },
-    { "lrm", 0x200e },
-    { "lsaquo", 0x2039 },
-    { "lsquo", 0x2018 },
-    { "lt", 60 },
-    { "macr", 0x00af },
-    { "mdash", 0x2014 },
-    { "micro", 0x00b5 },
-    { "middot", 0x00b7 },
-    { "minus", 0x2212 },
-    { "mu", 0x03bc },
-    { "nabla", 0x2207 },
-    { "nbsp", 0x00a0 },
-    { "ndash", 0x2013 },
-    { "ne", 0x2260 },
-    { "ni", 0x220b },
-    { "not", 0x00ac },
-    { "notin", 0x2209 },
-    { "nsub", 0x2284 },
-    { "ntilde", 0x00f1 },
-    { "nu", 0x03bd },
-    { "oacute", 0x00f3 },
-    { "ocirc", 0x00f4 },
-    { "oelig", 0x0153 },
-    { "ograve", 0x00f2 },
-    { "oline", 0x203e },
-    { "omega", 0x03c9 },
-    { "omicron", 0x03bf },
-    { "oplus", 0x2295 },
-    { "or", 0x22a6 },
-    { "ordf", 0x00aa },
-    { "ordm", 0x00ba },
-    { "oslash", 0x00f8 },
-    { "otilde", 0x00f5 },
-    { "otimes", 0x2297 },
-    { "ouml", 0x00f6 },
-    { "para", 0x00b6 },
-    { "part", 0x2202 },
-    { "percnt", 0x0025 },
-    { "permil", 0x2030 },
-    { "perp", 0x22a5 },
-    { "phi", 0x03c6 },
-    { "pi", 0x03c0 },
-    { "piv", 0x03d6 },
-    { "plusmn", 0x00b1 },
-    { "pound", 0x00a3 },
-    { "prime", 0x2032 },
-    { "prod", 0x220f },
-    { "prop", 0x221d },
-    { "psi", 0x03c8 },
-    { "quot", 34 },
-    { "rArr", 0x21d2 },
-    { "radic", 0x221a },
-    { "rang", 0x232a },
-    { "raquo", 0x00bb },
-    { "rarr", 0x2192 },
-    { "rceil", 0x2309 },
-    { "rdquo", 0x201d },
-    { "real", 0x211c },
-    { "reg", 0x00ae },
-    { "rfloor", 0x230b },
-    { "rho", 0x03c1 },
-    { "rlm", 0x200f },
-    { "rsaquo", 0x203a },
-    { "rsquo", 0x2019 },
-    { "sbquo", 0x201a },
-    { "scaron", 0x0161 },
-    { "sdot", 0x22c5 },
-    { "sect", 0x00a7 },
-    { "shy", 0x00ad },
-    { "sigma", 0x03c3 },
-    { "sigmaf", 0x03c2 },
-    { "sim", 0x223c },
-    { "spades", 0x2660 },
-    { "sub", 0x2282 },
-    { "sube", 0x2286 },
-    { "sum", 0x2211 },
-    { "sup1", 0x00b9 },
-    { "sup2", 0x00b2 },
-    { "sup3", 0x00b3 },
-    { "sup", 0x2283 },
-    { "supe", 0x2287 },
-    { "szlig", 0x00df },
-    { "tau", 0x03c4 },
-    { "there4", 0x2234 },
-    { "theta", 0x03b8 },
-    { "thetasym", 0x03d1 },
-    { "thinsp", 0x2009 },
-    { "thorn", 0x00fe },
-    { "tilde", 0x02dc },
-    { "times", 0x00d7 },
-    { "trade", 0x2122 },
-    { "uArr", 0x21d1 },
-    { "uacute", 0x00fa },
-    { "uarr", 0x2191 },
-    { "ucirc", 0x00fb },
-    { "ugrave", 0x00f9 },
-    { "uml", 0x00a8 },
-    { "upsih", 0x03d2 },
-    { "upsilon", 0x03c5 },
-    { "uuml", 0x00fc },
-    { "weierp", 0x2118 },
-    { "xi", 0x03be },
-    { "yacute", 0x00fd },
-    { "yen", 0x00a5 },
-    { "yuml", 0x00ff },
-    { "zeta", 0x03b6 },
-    { "zwj", 0x200d },
-    { "zwnj", 0x200c },
-    { "", 0x0000 }
-};
-
-static QMap<Q_UINT16, QCString> *HtmlMap = 0;
-
-HTMLReportElement::HTMLReportElement(Project* p, const QString& f, time_t s, time_t e,
-                                          const QString& df, int dl) :
-   Report(p, f, s, e, df, dl)
-{
-       colDefault = 0xf3ebae;
-       colDefaultLight = 0xfffadd;
-       colWeekend = 0xffec80;
-       colVacation = 0xfffc60;
-       colAvailable = 0xa4ff8d;
-       colBooked = 0xff5a5d;
-       colBookedLight = 0xffbfbf;
-       colHeader = 0xa5c2ff;
-       colMilestone = 0xff2a2a;
-       colCompleted = 0x87ff75;
-       colCompletedLight = 0xa1ff9a;
-       colToday = 0xa387ff;
-
-       barLabels = BLT_LOAD;
-
-       registerUrl(KW("dayheader"));
-       registerUrl(KW("monthheader"));
-       registerUrl(KW("resourcename"));
-       registerUrl(KW("taskname"));
-       registerUrl(KW("weekheader"));
-       registerUrl(KW("yearheader"));
-}
-
-void
-HTMLReportElement::generateTask1stRow(const Task* t, const Resource* r, uint no)
-{
-       s << "<tr valign=\"middle\">";
-       for (QStringList::Iterator it = columns.begin(); it != columns.end();
-                ++it )
-       {
-               if (*it == KW("seqno"))
-                       textMultiRows((r == 0 ? QString().sprintf("%d.",
-                                                                                                         t->getSequenceNo()) :
-                                                QString("")), r != 0, "");
-               else if (*it == KW("no"))
-                       textMultiRows((r == 0 ? QString().sprintf("%d.", no) :
-                                                QString("")), r != 0, "");
-               else if (*it == KW("index"))
-                       textMultiRows((r == 0 ? QString().sprintf("%d.", t->getIndex()) :
-                                                QString("")), r != 0, "");
-               else if (*it == KW("id"))
-                       textMultiRows(htmlFilter(t->getId()), r != 0, "left");
-               else if (*it == KW("name"))
-                       taskName(t, r, r == 0);
-               else if (*it == KW("start"))
-                       s << "<td class=\""
-                         << (t->isStartOk(scenarios[0]) ?
-                                 (r == 0 ? "default" : "defaultlight") : "milestone")
-                         << "\" style=\"text-align:left white-space:nowrap\">"
-                         << time2user(t->getStart(Task::Plan), timeFormat)
-                         << "</td>" << endl;
-               else if (*it == KW("end"))
-                       s << "<td class=\""
-                         << (t->isEndOk(Task::Plan) ?
-                                 (r == 0 ? "default" : "defaultlight") : "milestone")
-                         << "\" style=\"text-align:left white-space:nowrap\">"
-                         << time2user(t->getEnd(Task::Plan) + 1, timeFormat)
-                         << "</td>" << endl;
-               else if (*it == KW("minstart"))
-                       textMultiRows(time2user(t->getMinStart(), timeFormat), r != 0, "");
-               else if (*it == KW("maxstart"))
-                       textMultiRows(time2user(t->getMaxStart(), timeFormat),
-                                               r != 0, "");
-               else if (*it == KW("minend"))
-                       textMultiRows(time2user(t->getMinEnd(), timeFormat), r != 0, "");
-               else if (*it == KW("maxend"))
-                       textMultiRows(time2user(t->getMaxEnd(), timeFormat), r != 0, "");
-               else if (*it == KW("startbuffer"))
-                       textMultiRows(QString().sprintf
-                                               ("%3.0f", t->getStartBuffer(Task::Plan)), r != 0, 
-                                               "right");
-               else if (*it == KW("endbuffer"))
-                       textMultiRows(QString().sprintf
-                                               ("%3.0f", t->getEndBuffer(Task::Plan)), r != 0, 
-                                               "right");
-               else if (*it == KW("startbufferend"))
-                       textOneRow(time2user(t->getStartBufferEnd(Task::Plan) + 1,
-                                                                timeFormat), r != 0, "left");
-               else if (*it == KW("endbufferstart"))
-                       textOneRow(time2user(t->getEndBufferStart(Task::Plan), timeFormat),
-                                          r != 0, "left");
-               else if (*it == KW("duration"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(t->getCalcDuration(Task::Plan))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("effort"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(t->getLoad(Task::Plan, Interval(start, end), r))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("projectid"))
-                       textMultiRows(t->getProjectId() + " (" +
-                                               project->getIdIndex(t->getProjectId()) + ")", r != 0,
-                                               "left");
-               else if (*it == KW("resources"))
-                       scenarioResources(Task::Plan, t, r != 0);
-               else if (*it == KW("responsible"))
-                       if (t->getResponsible())
-                               textMultiRows(htmlFilter(t->getResponsible()->getName()), r != 0,
-                                                       "left");
-                       else
-                               textMultiRows("&nbsp", r != 0, "left");
-               else if (*it == KW("responsibilities"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("depends"))
-                       generateDepends(t, r != 0);
-               else if (*it == KW("follows"))
-                       generateFollows(t, r != 0);
-               else if (*it == KW("schedule"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("mineffort"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("maxeffort"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("rate"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("kotrusid"))
-                       emptyPlan(r != 0);
-               else if (*it == KW("note"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" rowspan=\""
-                         << (showActual ? "2" : "1")
-                         << "\" style=\"text-align:left\">"
-                         << "<span style=\"font-size:100%\">";
-                       if (t->getNote().isEmpty())
-                               s << "&nbsp;";
-                       else
-                               s << htmlFilter(t->getNote());
-                       s << "</span></td>" << endl;
-               }
-               else if (*it == KW("statusnote"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:left\">"
-                         << "<span style=\"font-size:100%\">";
-                       if (t->getStatusNote(Task::Plan).isEmpty())
-                               s << "&nbsp;";
-                       else
-                               s << htmlFilter(t->getStatusNote(Task::Plan));
-                       s << "</span></td>" << endl;
-               }
-               else if (*it == KW("costs"))
-                       textOneRow(
-                               QString().sprintf("%.*f", project->getCurrencyDigits(),
-                                                                 t->getCredits(Task::Plan,
-                                                                                               Interval(start, end), r)),
-                               r != 0,
-                               "right");
-               else if (*it == KW("priority"))
-                       textMultiRows(QString().sprintf("%d", t->getPriority()), r != 0,
-                                               "right");
-               else if (*it == KW("flags"))
-                       flagList(t, r);
-               else if (*it == KW("completed"))
-                       if (t->getCompletionDegree(Task::Plan) ==
-                               t->getCalcedCompletionDegree(Task::Plan))
-                       {
-                               textOneRow(QString("%1%")
-                                                  .arg((int) t->getCompletionDegree(Task::Plan)),
-                                                  r != 0, "right");
-                       }
-                       else
-                       {
-                               textOneRow(QString("%1% (%2%)")
-                                                  .arg((int) t->getCompletionDegree(Task::Plan))
-                                                  .arg((int) t->getCalcedCompletionDegree(Task::Plan)),
-                                                  r != 0, "right");
-                       }
-               else if (*it == KW("status"))
-                       generateTaskStatus(t->getStatus(Task::Plan), r != 0);
-               else if (*it == KW("daily"))
-                       dailyTaskPlan(t, r);
-               else if (*it == KW("weekly"))
-                       weeklyTaskPlan(t, r);
-               else if (*it == KW("monthly"))
-                       monthlyTaskPlan(t, r);
-               else
-                       qFatal("generatePlanTask: Unknown Column %s",
-                                  (*it).latin1());
-       }
-       s << "</tr>" << endl;
+void
+HTMLReportElement::generateHeader()
+{
+    if (!rawHead.isEmpty())
+    {
+        puts(rawHead);
+        puts("\n");
+    }
+    if (!headline.isEmpty())
+    {
+        puts("<h3>");
+        puts(htmlFilter(headline));
+        puts("</h3>\n");
+    }
+    if (!caption.isEmpty())
+    {
+        puts("<p>");
+        puts(htmlFilter(caption));
+        puts("</p>\n");
+    }
 }
 
 void
-HTMLReportElement::generateActualTask(const Task* t, const Resource* r)
+HTMLReportElement::generateFooter()
 {
-       s << "<tr>" << endl;
-       for (QStringList::Iterator it = columns.begin();
-                it != columns.end();
-                ++it )
-       {
-               if (*it == KW("start"))
-               {
-                       s << "<td class=\""
-                         << (t->isStartOk(Task::Actual) ?
-                                 (r == 0 ? "default" : "defaultlight") : "milestone")
-                         << "\" style=\"text-align:left white-space:nowrap\">"
-                         << time2user(t->getStart(Task::Actual), timeFormat)
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("end"))
-               {
-                       s << "<td class=\""
-                         << (t->isEndOk(Task::Actual) ?
-                                 (r == 0 ? "default" : "defaultlight") : "milestone")
-                         << "\" style=\"white-space:nowrap\">"
-                         << time2user(t->getEnd(Task::Actual) + 1, timeFormat)
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("startbufferend"))
-                       textOneRow(time2user(t->getStartBufferEnd(Task::Actual) + 1, 
-                                                                timeFormat), r != 0, "left");
-               else if (*it == KW("endbufferstart"))
-                       textOneRow(time2user(t->getEndBufferStart(Task::Actual), 
-                                                                timeFormat), r != 0, "left");
-               else if (*it == KW("duration"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(t->getCalcDuration(Task::Actual))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("effort"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(t->getLoad(Task::Actual, Interval(start, end), r))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("resources"))
-                       scenarioResources(Task::Actual, t, r != 0);
-               else if (*it == "costs")
-                       textOneRow(
-                               QString().sprintf("%.*f", project->getCurrencyDigits(),
-                                                                 t->getCredits(Task::Actual,
-                                                                                               Interval(start, end), r)),
-                               r != 0, "right");
-               else if (*it == KW("completed"))
-                       if (t->getCompletionDegree(Task::Actual) ==
-                               t->getCalcedCompletionDegree(Task::Actual))
-                       {
-                               textOneRow(QString("%1%")
-                                                  .arg((int) t->getCompletionDegree(Task::Actual)),
-                                                  r != 0, "right");
-                       }
-                       else
-                       {
-                               textOneRow(QString("%1% (%2%)")
-                                                  .arg((int) t->getCompletionDegree(Task::Actual))
-                                                  .arg((int)
-                                                               t->getCalcedCompletionDegree(Task::Actual)),
-                                                  r != 0, "right");
-                       }
-               else if (*it == KW("status"))
-                       generateTaskStatus(t->getStatus(Task::Actual), r != 0);
-               else if (*it == KW("statusnote"))
-               {
-                       s << "<td class=\""
-                         << (r == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:left\">"
-                         << "<span style=\"font-size:100%\">";
-                       if (t->getStatusNote(Task::Actual).isEmpty())
-                               s << "&nbsp;";
-                       else
-                               s << htmlFilter(t->getStatusNote(Task::Actual));
-                       s << "</span></td>" << endl;
-               }
-               else if (*it == KW("daily"))
-                       dailyTaskActual(t, r);
-               else if (*it == KW("weekly"))
-                       weeklyTaskActual(t, r);
-               else if (*it == KW("monthly"))
-                       monthlyTaskActual(t, r);
-       }
-       s << "</tr>" << endl;
+    if (!rawTail.isEmpty())
+    {
+        puts(rawTail);
+        puts("\n");
+    }
 }
 
 void
-HTMLReportElement::generatePlanResource(const Resource* r, const Task* t, uint no)
+HTMLReportElement::generateTableHeader()
 {
-       s << "<tr valign=\"middle\">";
-       for (QStringList::Iterator it = columns.begin(); it != columns.end();
-                ++it )
-       {
-               if (*it == KW("seqno"))
-                       textMultiRows((t == 0 ? QString().sprintf("%d.", r->getSequenceNo()) :
-                                                QString("")), t != 0, "");
-               else if (*it == KW("no"))
-                       textMultiRows((t == 0 ? QString().sprintf("%d.", no) :
-                                                QString("")), t != 0, "");
-               else if (*it == KW("index"))
-                       textMultiRows((t == 0 ? QString().sprintf("%d.", r->getIndex()) :
-                                                QString("")), t != 0, "");
-               else if (*it == KW("id"))
-                       textMultiRows(htmlFilter(r->getId()), t != 0, "left");
-               else if (*it == KW("name"))
-                       resourceName(r, t, FALSE);
-               else if (*it == KW("start"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("end"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("minstart"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("maxstart"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("minend"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("maxend"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("startbuffer"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("endbuffer"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("startbufferend"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("endbufferstart"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("duration"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("effort"))
-               {
-                       s << "<td class=\""
-                         << (t == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(r->getLoad(Task::Plan, Interval(start, end), t))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("projectid"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("resources"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("responsible"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("responsibilities"))
-                       generateResponsibilities(r, t != 0);
-               else if (*it == KW("depends"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("follows"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("schedule"))
-                       generateSchedule(Task::Plan, r, t);
-               else if (*it == KW("mineffort"))
-                       textMultiRows(QString().sprintf("%.2f", r->getMinEffort()), t != 0,
-                                               "right");
-               else if (*it == KW("maxeffort"))
-                       textMultiRows(QString().sprintf("%.2f", r->getMaxEffort()), t != 0,
-                                               "right");
-               else if (*it == KW("rate"))
-                       textMultiRows(QString().sprintf("%.*f", project->getCurrencyDigits(),
-                                                                                 r->getRate()), t != 0,
-                                               "right");
-               else if (*it == KW("kotrusid"))
-                       textMultiRows(r->getKotrusId(), t != 0, "left");
-               else if (*it == KW("note"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("costs"))
-                       textOneRow(
-                               QString().sprintf("%.*f", project->getCurrencyDigits(),
-                                                                 r->getCredits(Task::Plan,
-                                                                                               Interval(start, end), t)),
-                               t != 0, "right");
-               else if (*it == KW("priority"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("flags"))
-                       flagList(r, t);
-               else if (*it == KW("completed"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("status"))
-                       emptyPlan(t != 0);
-               else if (*it == KW("daily"))
-                       dailyResourcePlan(r, t);
-               else if (*it == KW("weekly"))
-                       weeklyResourcePlan(r, t);
-               else if (*it == KW("monthly"))
-                       monthlyResourcePlan(r, t);
-               else
-                       qFatal("generatePlanResource: Unknown Column %s",
-                                  (*it).latin1());
-       }
-       s << "</tr>" << endl;
+    // Header line 1
+    s() << "<table align=\"center\" cellpadding=\"2\" "
+        << "style=\"background-color:#000000\"";
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        s() << " class=\"tj_table\"";
+    s() << ">" << endl;
+    s() << " <thead>" << endl
+        << "  <tr valign=\"middle\""
+        << " style=\"background-color:" << colors.getColorName("header") << "; "
+        << "font-size:110%; font-weight:bold; text-align:center\"";
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        s() << " class=\"tj_header_row\"";
+    s() << ">" << endl;
+    for (QPtrListIterator<TableColumnInfo> it(columns); it; ++it )
+    {
+        if (columnFormat[(*it)->getName()])
+        {
+            TableCellInfo tci(columnFormat[(*it)->getName()], 0, *it);
+            (*this.*(columnFormat[(*it)->getName()]->genHeadLine1))
+                (&tci);
+        }
+        else if ((*it)->getName() == "costs")
+        {
+            TJMH.errorMessage
+                (i18n("'costs' has been deprecated. Use 'cost' instead."));
+            return;
+        }
+        else
+        {
+            TJMH.errorMessage
+                (i18n("Unknown Column '%1' for HTML Report")
+                 .arg((*it)->getName()));
+            return;
+        }
+    }
+    s() << "  </tr>" << endl;
+
+    // Header line 2
+    bool first = true;
+    for (QPtrListIterator<TableColumnInfo> it(columns); it; ++it )
+    {
+        if (columnFormat[(*it)->getName()])
+            if (columnFormat[(*it)->getName()]->genHeadLine2)
+            {
+                if (first)
+                {
+                    s() << "  <tr";
+                    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+                        s() << " class=\"tj_header_row\"";
+                    s() << ">" << endl;
+                    first = false;
+                }
+
+                TableCellInfo tci(columnFormat[(*it)->getName()], 0, *it);
+                (*this.*(columnFormat[(*it)->getName()]->genHeadLine2))
+                    (&tci);
+            }
+    }
+    if (!first)
+        s() << "  </tr>" << endl;
+
+    s() << " </thead>\n" << endl;
 }
 
 void
-HTMLReportElement::generateActualResource(const Resource* r, const Task* t)
+HTMLReportElement::generateLine(TableLineInfo* tli, int funcSel)
 {
-       s << "<tr valign=\"middle\">";
-       for (QStringList::Iterator it = columns.begin(); it != columns.end();
-                ++it )
-       {
-               if (*it == KW("effort"))
-               {
-                       s << "<td class=\""
-                         << (t == 0 ? "default" : "defaultlight")
-                         << "\" style=\"text-align:right white-space:nowrap\">"
-                         << scaledLoad(r->getLoad(Task::Actual, Interval(start, end), t))
-                         << "</td>" << endl;
-               }
-               else if (*it == KW("schedule"))
-                       generateSchedule(Task::Actual, r, t);
-               else if (*it == KW("costs"))
-                       textOneRow(
-                               QString().sprintf("%.*f", project->getCurrencyDigits(),
-                                                                 r->getCredits(Task::Actual,
-                                                                                               Interval(start, end), t)),
-                               t != 0,
-                               "right");
-               else if (*it == KW("daily"))
-                       dailyResourceActual(r, t);
-               else if (*it == KW("weekly"))
-                       weeklyResourceActual(r, t);
-               else if (*it == KW("monthly"))
-                       monthlyResourceActual(r, t);
-       }
-       s << "</tr>" << endl;
+    setMacros(tli);
+
+    puts("  <tr valign=\"middle\"");
+    if (tli->bgCol.isValid() || tli->boldText || tli->fontFactor != 100)
+    {
+       puts(" style=\"");
+       if (tli->bgCol.isValid())
+       {
+           puts("background-color:");
+           puts(tli->bgCol.name());
+           puts("; ");
+       }
+       if (tli->boldText)
+           puts("font-weight:bold; ");
+       if (tli->fontFactor != 100)
+       {
+           puts("font-size:");
+           puts(QString("%1").arg(tli->fontFactor));
+           puts("%; ");
+       }
+       puts("\"");
+    }
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        puts(" class=\"tj_row\"");
+    puts(">\n");
+
+    for (QPtrListIterator<TableColumnInfo> it(columns); it; ++it )
+    {
+        TableCellInfo tci(columnFormat[(*it)->getName()], tli, *it);
+        if (columnFormat[(*it)->getName()])
+        {
+            GenCellPtr gcf = 0;
+            switch (funcSel)
+            {
+                case 0:
+                    gcf = columnFormat[(*it)->getName()]->genHeadLine1;
+                    break;
+                case 1:
+                    gcf = columnFormat[(*it)->getName()]->genHeadLine2;
+                    break;
+                case 2:
+                    gcf = columnFormat[(*it)->getName()]->genTaskLine1;
+                    break;
+                case 3:
+                    gcf = columnFormat[(*it)->getName()]->genTaskLine2;
+                    break;
+                case 4:
+                    gcf = columnFormat[(*it)->getName()]->genResourceLine1;
+                    break;
+                case 5:
+                    gcf = columnFormat[(*it)->getName()]->genResourceLine2;
+                    break;
+                case 6:
+                    gcf = columnFormat[(*it)->getName()]->genAccountLine1;
+                    break;
+                case 7:
+                    gcf = columnFormat[(*it)->getName()]->genAccountLine2;
+                    break;
+                case 8:
+                    gcf = columnFormat[(*it)->getName()]->genSummaryLine1;
+                    break;
+                case 9:
+                    gcf = columnFormat[(*it)->getName()]->genSummaryLine2;
+                    break;
+                default:
+                    qFatal("Unknown function selector: %d", funcSel);
+            }
+            if (gcf)
+            {
+                (*this.*(gcf))(&tci);
+            }
+        }
+    }
+    puts("  </tr>\n");
 }
 
 void
-HTMLReportElement::reportHTMLHeader()
+HTMLReportElement::genCell(const QString& text, TableCellInfo* tci,
+                           bool multi, bool filter)
 {
-       s << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">"
-               << endl
-               << "<!-- Generated by TaskJuggler v"VERSION" -->" << endl
-               << "<!-- For details about TaskJuggler see "
-               << TJURL << " -->" << endl
-               << "<html>" << endl
-               << "<head>" << endl
-               << "<title>Task Report</title>" << endl
-               << "<style type=\"text/css\"><!--" << endl;
-       if (rawStyleSheet.isEmpty())
+    if (!multi)
+        tci->setFontFactor(90);
+
+    puts("   <td");
+    if (tci->tcf->noWrap)
+        puts(" nowrap=\"nowrap\"");
+    if (tci->getRows() != 1 || (multi && scenarios.count() > 1))
+        puts(" rowspan=\"" + QString("%1")
+             .arg(tci->getRows() != 1 ?
+                  tci->getRows() : scenarios.count()) + "\"");
+    if (tci->getColumns() != 1)
+    {
+        puts(" colspan=\"");
+        puts(QString("%1").arg(tci->getColumns()));
+        puts("\"");
+    }
+    if (!tci->getStatusText().isEmpty())
+    {
+        puts(" onmouseover=\"status='");
+        puts(tci->getStatusText());
+        puts("';return true;\"");
+    }
+    if (tci->tcf->hAlign != TableColumnFormat::center ||
+        !tci->getHAlign().isEmpty() ||
+        tci->getLeftPadding() > 0 ||
+        tci->getRightPadding() > 0 ||
+        tci->getBgColor().isValid() ||
+        tci->getFontFactor() != 100 ||
+        tci->getBoldText() ||
+        tci->tcf->fontFactor != 100)
+    {
+        puts(" style=\"");
+        if (tci->getBgColor().isValid())
+        {
+            puts("background-color:");
+            int r, g, b;
+            tci->getBgColor().rgb(&r, &g, &b);
+            char buf[10];
+            sprintf(buf, "#%02x%02x%02x; ", r, g, b);
+            puts(buf);
+        }
+        if (!tci->getHAlign().isEmpty())
+        {
+            puts("text-align:");
+            puts(tci->getHAlign());
+            puts("; ");
+        }
+        else if (tci->tcf->hAlign != TableColumnFormat::center)
+        {
+            puts("text-align:");
+            switch(tci->tcf->hAlign)
+            {
+                case TableColumnFormat::center:
+                    puts("center");
+                    break;
+                case TableColumnFormat::left:
+                    puts("left");
+                    break;
+                case TableColumnFormat::right:
+                    puts("right");
+                    break;
+            }
+            puts("; ");
+        }
+        if (tci->getLeftPadding() > 0)
+        {
+            puts("padding-left:");
+            puts(QString("%1").arg(tci->getLeftPadding()));
+            puts("; ");
+        }
+        if (tci->getRightPadding() > 0)
+        {
+            puts("padding-right:");
+            puts(QString("%1").arg(tci->getRightPadding()));
+            puts("; ");
+        }
+        if (tci->getBoldText())
+            puts("font-weight:bold; ");
+        if (tci->getFontFactor() != 100 || tci->tcf->fontFactor != 100)
+        {
+            puts("font-size:");
+            puts(QString("%1").arg(tci->getFontFactor() *
+                                   tci->tcf->fontFactor / 100));
+            puts("%; ");
+        }
+        puts("\"");
+    }
+    QString cellText;
+    if (tci->tli->ca1 == 0 ||
+        !isHidden(tci->tli->ca1, tci->tci->getHideCellText()))
+    {
+        cellText = filter ? htmlFilter(text) : text;
+        if (tci->tli->ca1 && !tci->tci->getCellText().isEmpty())
+        {
+            QStringList sl(text);
+            cellText = mt.expandReportVariable(tci->tci->getCellText(), &sl);
+        }
+    }
+    if (!tci->tci->getCellURL().isEmpty() && (tci->tli->ca1 == 0 ||
+        !isHidden(tci->tli->ca1, tci->tci->getHideCellURL())))
+    {
+        QStringList sl(text);
+        QString cellURL = mt.expandReportVariable(tci->tci->getCellURL(), &sl);
+       if (!cellURL.isEmpty())
        {
-               s.reset();
-               s.setf(QTextStream::hex);
-               s << ".default { background-color:#" << colDefault
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".defaultlight { background-color:#" << colDefaultLight
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".task { background-color:#" << colDefault
-                       << "; font-size:100%; text-align:left }" << endl
-                       << ".tasklight { background-color:#" << colDefaultLight
-                       << "; font-size:100%; text-align:left }" << endl
-                       << ".available { background-color:#" << colAvailable
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".vacation { background-color:#" << colVacation
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".weekend { background-color:#" << colWeekend
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".milestone { background-color:#" << colMilestone
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".booked { background-color:#" << colBooked
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".bookedlight { background-color:#" << colBookedLight
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".headersmall { background-color:#" << colHeader
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".headerbig { background-color:#" << colHeader
-                       << "; font-size:110%; font-weight:bold; text-align:center }" << endl
-                       << ".completed { background-color:#" << colCompleted
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".completedlight { background-color:#" << colCompletedLight
-                       << "; font-size:70%; text-align:center }" << endl
-                       << ".today { background-color:#" << colToday
-                       << "; font-size:70%; text-align:center }" << endl;
+           cellText = QString("<a href=\"") + cellURL
+                       + "\">" + cellText + "</a>";
        }
-       else
-               s << rawStyleSheet << endl;
-       s << "--></style>" << endl;
-       s << "</head>" << endl
-         << "<body>" << endl;
+    }
+    if (cellText.isEmpty())
+        cellText = "&#160;";
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        puts(" class=\"tj_cell\"");
+    puts(">");
+    if (!tci->getToolTipText().isEmpty())
+    {
+        puts("<div id=\"");
+        puts(tci->getToolTipID());
+        puts("\" class=\"tj_tooltip\" style=\"visibility:hidden\">");
+        puts(tci->getToolTipText());
+        puts("</div>");
+    }
 
-       if (!headline.isEmpty())
-               s << "<h1>" << htmlFilter(headline) << "</h1>" << endl;
-       if (!caption.isEmpty())
-               s << "<p>" << htmlFilter(caption) << "</p>" << endl;
-       if (!rawHead.isEmpty())
-               s << rawHead << endl;
+    puts(cellText);
+    puts("</td>\n");
 }
 
 void
-HTMLReportElement::reportHTMLFooter()
+HTMLReportElement::reportTaskLoad(double load, TableCellInfo* tci,
+                                  const Interval& period)
 {
-       if (!rawTail.isEmpty())
-               s << rawTail << endl;
+    QString text;
+    if (tci->tli->task->isActive(tci->tli->sc, period))
+    {
+        if (tci->tli->task->isContainer())
+        {
+            QString pre, post;
+            if (period.contains(tci->tli->task->getStart(tci->tli->sc)))
+                pre = "v=";
+            if (period.contains(tci->tli->task->getEnd(tci->tli->sc)))
+                post += "=v";
+            if (load > 0.0 && barLabels != BLT_EMPTY)
+                text = scaledLoad(load, tci->tcf->realFormat);
+            else if (pre.isEmpty() && post.isEmpty())
+                text = "==";
+            else if (!pre.isEmpty() && !post.isEmpty())
+            {
+                pre = post = "v";
+                text = "=";
+            }
+            text = pre + text + post;
+            tci->setBoldText(true);
+        }
+        else
+        {
+            if (tci->tli->task->isMilestone())
+            {
+                text += "<>";
+                tci->setBoldText(true);
+            }
+            else
+            {
+                QString pre, post;
+                if (period.contains(tci->tli->task->
+                                    getStart(tci->tli->sc)))
+                    pre = "[=";
+                if (period.contains(tci->tli->task->
+                                    getEnd(tci->tli->sc)))
+                    post = "=]";
+                if (!pre.isEmpty() && !post.isEmpty())
+                {
+                    pre = "[";
+                    post = "]";
+                }
+                if (load > 0.0 && barLabels != BLT_EMPTY)
+                    text = scaledLoad(load, tci->tcf->realFormat);
+                else if (pre.isEmpty() && post.isEmpty())
+                    text = "==";
+                else if (pre == "[")
+                   text = "=";
+                text = pre + text + post;
+            }
+        }
+        tci->setHAlign("center");
+        tci->setStatusText(time2user(period.getStart(), "%Y-%m-%d / [") +
+                           tci->tli->task->getId() + "] " +
+                           htmlFilter(tci->tli->task->getName()));
+    }
+    else
+    {
+        tci->setStatusText("");
+    }
+    genCell(text, tci, false);
+}
 
-       s << "<p><span style=\"font-size:0.7em\">";
-       if (!project->getCopyright().isEmpty())
-               s << htmlFilter(project->getCopyright()) << " - ";
-       s << "Version " << htmlFilter(project->getVersion())
-         << " - Created with <a HREF=\"" << TJURL <<
-         "\">TaskJuggler v"
-         << VERSION << "</a></span></p>" << endl << "</body>\n";
+void
+HTMLReportElement::reportResourceLoad(double load, TableCellInfo* tci,
+                                      const Interval& period)
+{
+    QString text;
+    if (load > 0.0)
+    {
+        if (barLabels != BLT_EMPTY)
+            text += scaledLoad(load, tci->tcf->realFormat);
+        if (tci->tli->resource->hasSubs())
+            tci->setBoldText(true);
+        tci->setHAlign("center");
+        tci->setStatusText(time2user(period.getStart(), "%Y-%m-%d / [") +
+                           tci->tli->resource->getId() + "] " +
+                           htmlFilter(tci->tli->resource->getName()));
+    }
+    else
+    {
+        tci->setStatusText("");
+    }
+    genCell(text, tci, false);
 }
 
-bool
-HTMLReportElement::generateTableHeader()
+void
+HTMLReportElement::reportCurrency(double value, TableCellInfo* tci,
+                                  time_t iv_start)
 {
-       // Header line 1
-       s << "<table align=\"center\" cellpadding=\"1\">\n" << endl;
-       s << "<tr>" << endl;
-       for (QStringList::Iterator it = columns.begin(); it != columns.end();
-                ++it )
-       {
-               if (*it == KW("seqno"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">" 
-                               << i18n("Seq. No.") << "</td>";
-               else if (*it == KW("no"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("No.") << "</td>";
-               else if (*it == KW("index"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Index No.") << "</td>";
-               else if (*it == KW("id"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("ID") << "</td>";
-               else if (*it == KW("name"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Name") << "</td>";
-               else if (*it == KW("start"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Start") << "</td>";
-               else if (*it == KW("end"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("End") << "</td>";
-               else if (*it == KW("minstart"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Min. Start") << "</td>";
-               else if (*it == KW("maxstart"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Max. Start") << "</td>";
-               else if (*it == KW("minend"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Min. End") << "</td>";
-               else if (*it == KW("maxend"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Max. End") << "</td>";
-               else if (*it == KW("startbufferend"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Start Buf. End") << "</td>";
-               else if (*it == KW("endbufferstart"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("End Buf. Start") << "</td>";
-               else if (*it == KW("startbuffer"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Start Buf.") << "</td>";
-               else if (*it == KW("endbuffer"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("End Buf.") << "</td>";
-               else if (*it == KW("duration"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Duration") << "</td>";
-               else if (*it == KW("effort"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Effort") << "</td>";
-               else if (*it == KW("projectid"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Project ID") << "</td>";
-               else if (*it == KW("resources"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Resources") << "</td>";
-               else if (*it == KW("responsible"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Responsible") << "</td>";
-               else if (*it == KW("responsibilities"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Responsibilities") << "</td>";
-               else if (*it == KW("depends"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Dependencies") << "</td>";
-               else if (*it == KW("follows"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Followers") << "</td>";
-               else if (*it == KW("schedule"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Schedule") << "</td>";
-               else if (*it == KW("mineffort"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Min. Effort") << "</td>";
-               else if (*it == KW("maxeffort"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Max. Effort") << "</td>";
-               else if (*it == KW("flags"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Flags") << "</td>";
-               else if (*it == KW("completed"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Completed") << "</td>";
-               else if (*it == KW("status"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Status") << "</td>";
-               else if (*it == KW("rate"))
-               {
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Rate");
-                       if (!project->getCurrency().isEmpty())
-                               s << " " << htmlFilter(project->getCurrency());
-                       s << "</td>";
-               }
-               else if (*it == KW("kotrusid"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Kotrus ID") << "</td>";
-               else if (*it == KW("note"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Note") << "</td>";
-               else if (*it == KW("statusnote"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Status Note") << "</td>";
-               else if (*it == KW("costs"))
-               {
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Costs");
-                       if (!project->getCurrency().isEmpty())
-                               s << " " << htmlFilter(project->getCurrency());
-                       s << "</td>";
-               }
-               else if (*it == KW("priority"))
-                       s << "<td class=\"headerbig\" rowspan=\"2\">"
-                               << i18n("Priority") << "</td>";
-               else if (*it == KW("daily"))
-                       htmlDailyHeaderMonths();
-               else if (*it == KW("weekly"))
-                       htmlWeeklyHeaderMonths();
-               else if (*it == KW("monthly"))
-                       htmlMonthlyHeaderYears();
-               else
-               {
-                       TJMH.errorMessage
-                               (i18n("Unknown Column '%1' for HTML Task Report")
-                                .arg(*it));
-                       return FALSE;
-               }
-       }
-       s << "</tr>" << endl;
+    tci->setStatusText(time2user(iv_start, "%Y-%m-%d / [") +
+                       tci->tli->account->getId() + "] " +
+                       htmlFilter(tci->tli->account->getName()));
+    genCell(tci->tcf->realFormat.format(value, tci), tci, false);
+}
 
-       // Header line 2
-       bool td = FALSE;
-       s << "<tr>" << endl;
-       for (QStringList::Iterator it = columns.begin(); it != columns.end();
-                ++it )
-       {
-               if (*it == KW("daily"))
-               {
-                       td = TRUE;
-                       htmlDailyHeaderDays();
-               }
-               else if (*it == KW("weekly"))
-               {
-                       td = TRUE;
-                       htmlWeeklyHeaderWeeks();
-               }
-               else if (*it == KW("monthly"))
-               {
-                       td = TRUE;
-                       htmlMonthlyHeaderMonths();
-               }
-       }
-       if (!td)
-               s << "<td>&nbsp;</td>";
-       s << "</tr>\n" << endl;
+void
+HTMLReportElement::generateTitle(TableCellInfo* tci, const QString& str)
+{
+    QStringList sl(str);
+    QString cellText;
+    if (!tci->tci->getTitle().isEmpty())
+        cellText = mt.expandReportVariable(tci->tci->getTitle(), &sl);
+    else
+        cellText = str;
+    cellText = htmlFilter(cellText);
+    QString cellURL = mt.expandReportVariable(tci->tci->getTitleURL(), &sl);
+    if (!cellURL.isEmpty())
+        cellText = QString("<a href=\"") + cellURL
+            + "\">" + cellText + "</a>";
+
+    puts(cellText);
+}
 
-       return TRUE;
+void
+HTMLReportElement::generateSubTitle(TableCellInfo* tci, const QString& str)
+{
+    QStringList sl(str);
+    QString cellText;
+    if (!tci->tci->getSubTitle().isEmpty())
+        cellText = mt.expandReportVariable(tci->tci->getSubTitle(), &sl);
+    else
+        cellText = str;
+    cellText = htmlFilter(cellText);
+    QString cellURL = mt.expandReportVariable(tci->tci->getSubTitleURL(), &sl);
+    if (!cellURL.isEmpty())
+        cellText = QString("<a href=\"") + cellURL
+            + "\">" + cellText + "</a>";
+
+    puts(cellText);
+
+    tci->tci->increaseSubColumns();
 }
 
 void
-HTMLReportElement::htmlDailyHeaderDays(bool highlightNow)
+HTMLReportElement::generateRightIndented(TableCellInfo* tci, const QString& str)
 {
-       // Generates the 2nd header line for daily calendar views.
-       for (time_t day = midnight(start); day < end; day = sameTimeNextDay(day))
-       {
-               int dom = dayOfMonth(day);
-               s << "<td class=\"" <<
-                       (highlightNow && isSameDay(project->getNow(), day) ?
-                        "today" : isWeekend(day) ? "weekend" : "headersmall")
-                 << "\"><span style=\"font-size:0.8em\">&nbsp;";
-               mt.clear();
-               mt.addMacro(new Macro(KW("day"), QString().sprintf("%02d", dom),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfYear(day)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", year(day)),
-                                                         defFileName, defFileLine));
-               if (dom < 10)
-                       s << "&nbsp;";
-               s << generateUrl(KW("dayheader"), QString().sprintf("%d", dom));
-               s << "</span></td>";
-       }
+    int topIndent = 0, subIndent = 0, maxDepth = 0;
+    if (tci->tli->ca1->getType() == CA_Task)
+    {
+        if (taskSortCriteria[0] == CoreAttributesList::TreeMode)
+            subIndent = tci->tli->ca2 == 0 ? 8 : 5;
+        if (resourceSortCriteria[0] == CoreAttributesList::TreeMode)
+            topIndent = (tci->tli->ca2 != 0 ? 0 : 5) * maxDepthResourceList;
+        maxDepth = maxDepthTaskList;
+    }
+    else if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        if (resourceSortCriteria[0] == CoreAttributesList::TreeMode)
+            subIndent = tci->tli->ca2 == 0 ? 8 : 5;
+        if (taskSortCriteria[0] == CoreAttributesList::TreeMode)
+            topIndent = (tci->tli->ca2 != 0 ? 0 : 5) * maxDepthTaskList;
+        maxDepth = maxDepthResourceList;
+    }
+
+    tci->setRightPadding(2 + topIndent +
+                         (maxDepth - 1 - tci->tli->ca1->treeLevel()) *
+                         subIndent);
+    genCell(str, tci, false);
 }
 
 void
-HTMLReportElement::htmlDailyHeaderMonths()
+HTMLReportElement::genHeadDefault(TableCellInfo* tci)
 {
-       // Generates the 1st header line for daily calendar views.
-       if (!hidePlan && showActual)
-               s << "<td class=\"headerbig\" rowspan=\"2\">&nbsp;</td>";
+    puts("   <td rowspan=\"2\"");
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        puts(" class=\"tj_header_cell\"");
+    puts(">");
+    generateTitle(tci, tci->tcf->getTitle());
+    puts("</td>\n");
+}
 
-       for (time_t day = midnight(start); day < end;
-                day = beginOfMonth(sameTimeNextMonth(day)))
-       {
-               int left = daysLeftInMonth(day);
-               if (left > daysBetween(day, end))
-                       left = daysBetween(day, end);
-               s << "<td class=\"headerbig\" colspan=\""
-                       << QString().sprintf("%d", left) << "\">"; 
-               mt.clear();
-               mt.addMacro(new Macro(KW("day"), QString().sprintf("%02d",
-                                                                                                                  dayOfMonth(day)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfYear(day)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", year(day)),
-                                                         defFileName, defFileLine));
-               s << generateUrl(KW("monthheader"), monthAndYear(day)); 
-               s << "</td>" << endl;
-       }
+void
+HTMLReportElement::genHeadCurrency(TableCellInfo* tci)
+{
+    puts("   <td rowspan=\"2\"");
+    if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+        puts(" class=\"tj_header_cell\"");
+    puts(">");
+    generateTitle(tci, tci->tcf->getTitle() +
+                  (!report->getProject()->getCurrency().isEmpty() ?
+                   QString(" ") + report->getProject()->getCurrency() :
+                   QString()));
+    puts("</td>\n");
 }
 
 void
-HTMLReportElement::htmlWeeklyHeaderWeeks(bool highlightNow)
+HTMLReportElement::genHeadDaily1(TableCellInfo* tci)
 {
-       // Generates the 2nd header line for weekly calendar views.
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
-                week = sameTimeNextWeek(week))
-       {
-               int woy = weekOfYear(week, weekStartsMonday);
-               s << "<td class=\"" <<
-                       (highlightNow && isSameWeek(project->getNow(), week,
-                                                                               weekStartsMonday) ?
-                        "today" : "headersmall")
-                 << "\"><span style=\"font-size:0.8em\">&nbsp;";
-               if (woy < 10)
-                       s << "&nbsp;";
-               mt.clear();
-               mt.addMacro(new Macro(KW("day"), QString().sprintf("%02d",
-                                                                                                                  dayOfMonth(woy)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfYear(woy)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", year(woy)),
-                                                         defFileName, defFileLine));
-               s << generateUrl(KW("weekheader"), QString().sprintf("%d", woy));
-               s << "</span></td>";
-       }
+    // Generates the 1st header line for daily calendar views.
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t day = midnight(start); day < end;
+         day = sameTimeNextMonth(beginOfMonth(day)))
+    {
+        int left = daysLeftInMonth(day);
+        if (left > daysBetween(day, end))
+            left = daysBetween(day, end);
+        s() << "   <td colspan=\""
+            << QString().sprintf("%d", left) << "\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d", monthOfYear(day)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf
+                              ("%02d", quarterOfYear(day)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf
+                              ("%02d", weekOfYear(day, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", year(day)),
+                              defFileName, defFileLine));
+        generateTitle(tci, monthAndYear(day));
+        s() << "</td>" << endl;
+    }
 }
 
 void
-HTMLReportElement::htmlWeeklyHeaderMonths()
+HTMLReportElement::genHeadDaily2(TableCellInfo* tci)
 {
-       static const char* mnames[] =
-       {
-               I18N_NOOP("Jan"), I18N_NOOP("Feb"), I18N_NOOP("Mar"),
-               I18N_NOOP("Apr"), I18N_NOOP("May"), I18N_NOOP("Jun"),
-               I18N_NOOP("Jul"), I18N_NOOP("Aug"), I18N_NOOP("Sep"), 
-               I18N_NOOP("Oct"), I18N_NOOP("Nov"), I18N_NOOP("Dec")
-       };
-       // Generates the 1st header line for weekly calendar views.
-       if (!hidePlan && showActual)
-               s << "<td class=\"headerbig\" rowspan=\"2\">&nbsp;</td>";
+    // Generates the 2nd header line for daily calendar views.
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t day = midnight(start); day < end; day = sameTimeNextDay(day))
+    {
+        int dom = dayOfMonth(day);
+        s() << "   <td style=\"";
+        QColor bgCol = colors.getColor("header");
+        if (isWeekend(day))
+            bgCol = bgCol.dark(130);
+        if (isSameDay(report->getProject()->getNow(), day))
+            bgCol = colors.getColor("today");
+        s() << "background-color:" << bgCol.name() << "; "
+            << "font-size:80%; text-align:center\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), QString().sprintf("%02d", dom),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d", monthOfYear(day)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf
+                              ("%02d", quarterOfYear(day)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf
+                              ("%02d", weekOfYear(day, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", year(day)),
+                              defFileName, defFileLine));
+        if (dom < 10)
+            s() << "&#160;";
+        generateSubTitle(tci, QString().sprintf("%d", dom));
+        s() << "</td>" << endl;
+    }
+}
 
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end; )
-       {
-               int currMonth = monthOfWeek(week, weekStartsMonday);
-               int left;
-               time_t wi = sameTimeNextWeek(week);
-               for (left = 1 ; wi < end &&
-                        monthOfWeek(wi, weekStartsMonday) == currMonth;
-                        wi = sameTimeNextWeek(wi))
-                       left++;
-                        
-               s << "<td class=\"headerbig\" colspan=\""
-                 << QString().sprintf("%d", left) << "\">";
-               mt.clear();
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfWeek(week,
-                                                                                                                       weekStartsMonday)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", yearOfWeek(week,
-                                                                                                                       weekStartsMonday)),
-                                                         defFileName, defFileLine));
-               s << generateUrl(KW("monthheader"), 
-                                                QString("%1 %2").
-                                                arg(i18n(mnames[monthOfWeek(week, weekStartsMonday) -
-                                                                 1])).
-                                                arg(yearOfWeek(week, weekStartsMonday)));
-               s << "</td>" << endl;
-               week = wi;
-       }
+void
+HTMLReportElement::genHeadWeekly1(TableCellInfo* tci)
+{
+    // Generates the 1st header line for weekly calendar views.
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t week = beginOfWeek(start, weekStartsMonday); week < end; )
+    {
+        int currMonth = monthOfWeek(week, weekStartsMonday);
+        int left;
+        time_t wi = sameTimeNextWeek(week);
+        for (left = 1 ; wi < end &&
+             monthOfWeek(wi, weekStartsMonday) == currMonth;
+             wi = sameTimeNextWeek(wi))
+            left++;
+
+        s() << "   <td colspan=\""
+          << QString().sprintf("%d", left) << "\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), QString().sprintf
+                              ("%02d", dayOfMonth(week)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf
+                              ("%02d", monthOfWeek(week, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf
+                              ("%02d", quarterOfYear(week)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf
+                              ("%02d", weekOfYear(week, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf
+                              ("%04d", yearOfWeek(week, weekStartsMonday)),
+                              defFileName, defFileLine));
+        generateTitle(tci,
+                      QString("%1 %2").arg(shortMonthName(monthOfWeek(week,
+                                                          weekStartsMonday)
+                                                          - 1)).
+                      arg(yearOfWeek(week, weekStartsMonday)));
+        s() << "</td>" << endl;
+        week = wi;
+    }
 }
 
 void
-HTMLReportElement::htmlMonthlyHeaderMonths(bool highlightNow)
+HTMLReportElement::genHeadWeekly2(TableCellInfo* tci)
 {
-       // Generates 2nd header line of monthly calendar view.
-       static const char* mnames[] =
-       {
-               I18N_NOOP("Jan"), I18N_NOOP("Feb"), I18N_NOOP("Mar"),
-               I18N_NOOP("Apr"), I18N_NOOP("May"), I18N_NOOP("Jun"),
-               I18N_NOOP("Jul"), I18N_NOOP("Aug"), I18N_NOOP("Sep"), 
-               I18N_NOOP("Oct"), I18N_NOOP("Nov"), I18N_NOOP("Dec")
-       };
+    // Generates the 2nd header line for weekly calendar views.
+    bool wsm = report->getWeekStartsMonday();
+    for (time_t week = beginOfWeek(start, wsm); week < end;
+         week = sameTimeNextWeek(week))
+    {
+        int woy = weekOfYear(week, wsm);
+        s() << "   <td style=\"";
+        QColor bgCol;
+        if (isSameWeek(report->getProject()->getNow(), week, wsm))
+            bgCol = colors.getColor("today");
+        else
+            bgCol = colors.getColor("header");
+        s() << "background-color:" << bgCol.name() << "; "
+            << "font-size:80%; text-align:center\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        if (woy < 10)
+            s() << "&#160;";
+        mt.setMacro(new Macro(KW("day"), QString().sprintf
+                              ("%02d", dayOfMonth(week)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d",
+                                                monthOfWeek(week, wsm)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf
+                              ("%02d", quarterOfYear(week)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf("%02d", woy),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", yearOfWeek(week, wsm)),
+                              defFileName, defFileLine));
+        generateSubTitle(tci, QString().sprintf("%d", woy));
+        s() << "</td>" << endl;
+    }
+}
 
-       for (time_t month = beginOfMonth(start); month < end;
-                month = sameTimeNextMonth(month))
-       {
-               int moy = monthOfYear(month);
-               s << "<td class=\"" <<
-                       (highlightNow && isSameMonth(project->getNow(), month) ?
-                        "today" : "headersmall")
-                 << "\"><span style=\"font-size:0.8em\">&nbsp;";
-               mt.clear();
-               mt.addMacro(new Macro(KW("day"), QString().sprintf("%02d",
-                                                                                                                  dayOfMonth(moy)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfYear(moy)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", year(moy)),
-                                                         defFileName, defFileLine));
-               s << generateUrl(KW("monthheader"), i18n(mnames[moy - 1]));
-               s << "</span></td>";
-       }
+void
+HTMLReportElement::genHeadMonthly1(TableCellInfo* tci)
+{
+    // Generates 1st header line of monthly calendar view.
+    for (time_t year = beginOfMonth(start); year < end;
+         year = sameTimeNextYear(beginOfYear(year)))
+    {
+        int left = monthLeftInYear(year);
+        if (left > monthsBetween(year, end))
+            left = monthsBetween(year, end);
+        s() << "   <td colspan=\""
+          << QString().sprintf("%d", left) << "\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"), "1",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", ::year(year)),
+                              defFileName, defFileLine));
+        generateTitle(tci, QString().sprintf("%d", ::year(year)));
+        s() << "</td>" << endl;
+    }
 }
 
 void
-HTMLReportElement::htmlMonthlyHeaderYears()
+HTMLReportElement::genHeadMonthly2(TableCellInfo* tci)
 {
-       // Generates 1st header line of monthly calendar view.
-       if (!hidePlan && showActual)
-               s << "<td class=\"headerbig\" rowspan=\"2\">&nbsp;</td>";
+    // Generates 2nd header line of monthly calendar view.
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t month = beginOfMonth(start); month < end;
+         month = sameTimeNextMonth(month))
+    {
+        int moy = monthOfYear(month);
+        s() << "   <td style=\"";
+        QColor bgCol;
+        if (isSameMonth(report->getProject()->getNow(), month))
+            bgCol = colors.getColor("today");
+        else
+            bgCol = colors.getColor("header");
+        s() << "background-color:" << bgCol.name() << "; "
+            << "font-size:80%; text-align:center\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        if (month < 10)
+            s() << "&#160;";
+        mt.setMacro(new Macro(KW("day"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d", moy),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf
+                              ("%02d", quarterOfYear(month)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf
+                              ("%02d", weekOfYear(month, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", year(month)),
+                              defFileName, defFileLine));
+        generateSubTitle(tci, shortMonthName(moy - 1));
+        s() << "</td>" << endl;
+    }
+}
 
-       for (time_t year = midnight(start); year < end;
-                year = beginOfYear(sameTimeNextYear(year)))
-       {
-               int left = monthLeftInYear(year);
-               if (left > monthsBetween(year, end))
-                       left = monthsBetween(year, end);
-               s << "<td class=\"headerbig\" colspan=\""
-                 << QString().sprintf("%d", left) << "\">";
-               mt.clear();
-               mt.addMacro(new Macro(KW("day"), QString().sprintf("%02d",
-                                                                                                                  dayOfMonth(year)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("month"),
-                                                         QString().sprintf("%02d", monthOfYear(year)),
-                                                         defFileName, defFileLine));
-               mt.addMacro(new Macro(KW("year"),
-                                                         QString().sprintf("%04d", ::year(year)),
-                                                         defFileName, defFileLine));
-               s << generateUrl(KW("yearheader"),
-                                                QString().sprintf("%d", ::year(year)));
-               s << "</td>" << endl;
-       }
+void
+HTMLReportElement::genHeadQuarterly1(TableCellInfo* tci)
+{
+    // Generates 1st header line of quarterly calendar view.
+    for (time_t year = beginOfQuarter(start); year < end;
+         year = sameTimeNextYear(beginOfYear(year)))
+    {
+        int left = quartersLeftInYear(year);
+        if (left > quartersBetween(year, end))
+            left = quartersBetween(year, end);
+        s() << "   <td colspan=\""
+          << QString().sprintf("%d", left) << "\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"), "1",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", ::year(year)),
+                              defFileName, defFileLine));
+        generateTitle(tci, QString().sprintf("%d", ::year(year)));
+        s() << "</td>" << endl;
+    }
 }
 
 void
-HTMLReportElement::emptyPlan(bool light)
+HTMLReportElement::genHeadQuarterly2(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" rowspan=\""
-         << (showActual ? "2" : "1")
-         << "\">&nbsp;</td>";
+    // Generates 2nd header line of quarterly calendar view.
+    static const char* qnames[] =
+    {
+        I18N_NOOP("1st Quarter"), I18N_NOOP("2nd Quarter"),
+        I18N_NOOP("3rd Quarter"), I18N_NOOP("4th Quarter")
+    };
+
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t quarter = beginOfQuarter(start); quarter < end;
+         quarter = sameTimeNextQuarter(quarter))
+    {
+        int qoy = quarterOfYear(quarter);
+        s() << "   <td style=\"";
+        QColor bgCol;
+        if (isSameQuarter(report->getProject()->getNow(), quarter))
+            bgCol = colors.getColor("today");
+        else
+            bgCol = colors.getColor("header");
+        s() << "background-color:" << bgCol.name() << "; "
+            << "font-size:80%; text-align:center\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), QString().sprintf("%02d",
+                                                           dayOfMonth(quarter)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d", monthOfYear(quarter)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"),
+                              QString().sprintf("%d", qoy),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"),
+                              QString().sprintf
+                              ("%02d", weekOfYear(quarter, weekStartsMonday)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", year(quarter)),
+                              defFileName, defFileLine));
+        generateSubTitle(tci, i18n(qnames[qoy - 1]));
+        s() << "</td>" << endl;
+    }
 }
 
 void
-HTMLReportElement::emptyActual(bool light)
+HTMLReportElement::genHeadYear(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\">&nbsp;</td>";
+    // Generates 1st header line of monthly calendar view.
+    for (time_t year = beginOfYear(start); year < end;
+         year = sameTimeNextYear(year))
+    {
+        s() << "   <td rowspan=\"2\"";
+        if (static_cast<HTMLReport*>(report)->hasStyleSheet())
+            s() << " class=\"tj_header_cell\"";
+        s() << ">";
+        mt.setMacro(new Macro(KW("day"), QString().sprintf("%02d",
+                                                           dayOfMonth(year)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("month"),
+                              QString().sprintf("%02d", monthOfYear(year)),
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("quarter"), "1",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("week"), "01",
+                              defFileName, defFileLine));
+        mt.setMacro(new Macro(KW("year"),
+                              QString().sprintf("%04d", ::year(year)),
+                              defFileName, defFileLine));
+        generateTitle(tci, QString().sprintf("%d", ::year(year)));
+        s() << "</td>" << endl;
+    }
 }
 
 void
-HTMLReportElement::textOneRow(const QString& text, bool light, const QString& align)
+HTMLReportElement::genCellEmpty(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default") << "\"";
-       if (!align.isEmpty())
-               s << " style=\"text-align:" << align << " white-space:nowrap\"";
-       s << ">" << text << "</td>";
+    genCell("", tci, true);
 }
 
 void
-HTMLReportElement::textMultiRows(const QString& text, bool light, 
-                                                                const QString& align)
+HTMLReportElement::genCellSequenceNo(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" rowspan=\""
-         << scenarios.count() << "\"";
-       if (!align.isEmpty())
-               s << " style=\"text-align:" << align << "; white-space:nowrap\"";
-       s << ">" << text << "</td>";
+    genCell(tci->tli->ca2 == 0 ?
+            QString().sprintf("%d.", tci->tli->ca1->getSequenceNo()) :
+            QString::null, tci, true);
 }
 
 void
-HTMLReportElement::dailyResourcePlan(const Resource* r, const Task* t)
+HTMLReportElement::genCellNo(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    genCell(tci->tli->ca2 == 0 ? QString().sprintf("%d.", tci->tli->idxNo) :
+            QString::null, tci, true);
+}
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+void
+HTMLReportElement::genCellHierarchNo(TableCellInfo* tci)
+{
+    genCell(tci->tli->ca2 == 0 ?
+            tci->tli->ca1->getHierarchNo() : QString::null, tci, true);
+}
 
-       for (time_t day = midnight(start); day < end;
-                day = sameTimeNextDay(day))
-       {
-               double load = r->getLoad(Task::Plan, Interval(day).firstDay(), t);
-               QString bgCol = 
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" : "bookedlight") :
-                       isSameDay(project->getNow(), day) ? "today" :
-                       isWeekend(day) ? "weekend" :
-                       project->isVacation(day) || r->hasVacationDay(day) ?
-                       "vacation" :
-                       (t == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !r->isGroup());
-       }
+void
+HTMLReportElement::genCellIndex(TableCellInfo* tci)
+{
+    genCell(tci->tli->ca2 == 0 ?
+            QString().sprintf("%d.", tci->tli->ca1->getIndex()) :
+            QString::null, tci, true);
 }
 
 void
-HTMLReportElement::dailyResourceActual(const Resource* r, const Task* t)
+HTMLReportElement::genCellHierarchIndex(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    genCell(tci->tli->ca2 == 0 ?
+            tci->tli->ca1->getHierarchIndex() : QString::null, tci, true);
+}
 
-       for (time_t day = midnight(start); day < end;
-                day = sameTimeNextDay(day))
-       {
-               double load = r->getLoad(Task::Actual, Interval(day).firstDay(), t);
-               QString bgCol = 
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" :
-                        (t->isCompleted(Task::Plan, sameTimeNextDay(day) - 1) ?
-                         "completedlight" : "bookedlight")) :
-                       isSameDay(project->getNow(), day) ? "today" :
-                       isWeekend(day) ? "weekend" :
-                       project->isVacation(day) || r->hasVacationDay(day) ?
-                       "vacation" :
-                       (t == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !r->isGroup());
-       }
+void
+HTMLReportElement::genCellId(TableCellInfo* tci)
+{
+    genCell(tci->tli->ca1->getId(), tci, true);
 }
 
-void 
-HTMLReportElement::dailyTaskPlan(const Task* t, const Resource* r)
+void
+HTMLReportElement::genCellName(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    int lPadding = 0;
+    int fontSize = tci->tli->ca2 == 0 ? 100 : 90;
+    if ((tci->tli->ca2 && tci->tli->ca2->getType() == CA_Resource &&
+          resourceSortCriteria[0] == CoreAttributesList::TreeMode) ||
+        (tci->tli->ca2 && tci->tli->ca2->getType() == CA_Task &&
+         taskSortCriteria[0] == CoreAttributesList::TreeMode) ||
+        (tci->tli->ca2 && tci->tli->ca2->getType() == CA_Account &&
+          accountSortCriteria[0] == CoreAttributesList::TreeMode))
+        for (const CoreAttributes* cp = tci->tli->ca2 ; cp != 0;
+             cp = cp->getParent())
+            lPadding++;
+
+    QString text;
+    if (tci->tli->specialName.isNull())
+    {
+        if (tci->tli->task)
+            mt.setMacro(new Macro(KW("taskid"), tci->tli->task->getId(),
+                                  defFileName, defFileLine));
+        if (tci->tli->resource)
+            mt.setMacro(new Macro(KW("resourceid"), tci->tli->resource->getId(),
+                                  defFileName, defFileLine));
+        if (tci->tli->account)
+            mt.setMacro(new Macro(KW("accountid"), tci->tli->account->getId(),
+                                  defFileName, defFileLine));
+
+        if ((tci->tli->ca1->getType() == CA_Resource &&
+             resourceSortCriteria[0] == CoreAttributesList::TreeMode) ||
+            (tci->tli->ca1->getType() == CA_Task &&
+             taskSortCriteria[0] == CoreAttributesList::TreeMode) ||
+            (tci->tli->ca1->getType() == CA_Account &&
+             accountSortCriteria[0] == CoreAttributesList::TreeMode))
+        {
+            lPadding += tci->tli->ca1->treeLevel();
+            tci->setFontFactor(fontSize + 5 * (maxDepthTaskList - 1 -
+                                               tci->tli->ca1->treeLevel()));
+        }
+        tci->setLeftPadding(2 + lPadding * 15);
+        text = tci->tli->ca1->getName();
+    }
+    else
+        text = tci->tli->specialName;
+    genCell(text, tci, true);
+}
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+void
+HTMLReportElement::genCellStart(TableCellInfo* tci)
+{
+    if (!tci->tli->task->isStartOk(tci->tli->sc))
+        tci->setBgColor(colors.getColor("error"));
+    genCell(time2user(tci->tli->task->getStart(tci->tli->sc), timeFormat),
+            tci, false);
+}
 
-       for (time_t day = midnight(start); day < end;
-                day = sameTimeNextDay(day))
-       {
-               double load = t->getLoad(Task::Plan, Interval(day).firstDay(), r);
-               QString bgCol = 
-                       t->isActive(Task::Plan, Interval(day).firstDay()) ?
-                       (t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Plan, Interval(day).firstDay()) ?
-                         "booked" : "bookedlight")) :
-                       isSameDay(project->getNow(), day) ? "today" :
-                       isWeekend(day) ? "weekend" :
-                       project->isVacation(day) ? "vacation" :
-                       (r == 0 ? "default" : "defaultlight");
-               if (showPIDs)
-               {
-                       QString pids = r->getProjectIDs(Task::Plan,
-                                                                                       Interval(day).firstDay(), t);
-                       reportPIDs(pids, bgCol, !r->isGroup());
-               }
-               else
-               reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellEnd(TableCellInfo* tci)
+{
+    if (!tci->tli->task->isEndOk(tci->tli->sc))
+        tci->setBgColor(colors.getColor("error"));
+    genCell(time2user(tci->tli->task->getEnd(tci->tli->sc) + 1, timeFormat),
+            tci, false);
 }
 
+#define GCMMSE(a, b) \
+void \
+HTMLReportElement::genCell##a(TableCellInfo* tci) \
+{ \
+    genCell(tci->tli->task->get##a(tci->tli->sc) == 0 ? QString() : \
+            time2user(tci->tli->task->get##a(tci->tli->sc) + b, timeFormat), \
+            tci, false); \
+}
+
+GCMMSE(MinStart, 0)
+GCMMSE(MaxStart, 0)
+GCMMSE(MinEnd, 1)
+GCMMSE(MaxEnd, 1)
+
+#define GCSEBUFFER(a) \
+void \
+HTMLReportElement::genCell##a##Buffer(TableCellInfo* tci) \
+{ \
+    genCell(QString().sprintf \
+            ("%3.0f", tci->tli->task->get##a##Buffer(tci->tli->sc)), \
+            tci, false); \
+}
+
+GCSEBUFFER(Start)
+GCSEBUFFER(End)
+
 void
-HTMLReportElement::dailyTaskActual(const Task* t, const Resource* r)
+HTMLReportElement::genCellStartBufferEnd(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    genCell(time2user(tci->tli->task->getStartBufferEnd
+                         (tci->tli->sc), timeFormat), tci, false);
+}
 
-       for (time_t day = midnight(start); day < end;
-                day = sameTimeNextDay(day))
-       {
-               double load = t->getLoad(Task::Actual, Interval(day).firstDay(), r);
-               QString bgCol = 
-                       t->isActive(Task::Actual, Interval(day).firstDay()) ? 
-                       (t->isCompleted(Task::Plan, sameTimeNextDay(day) - 1) ?
-                        (r == 0 ? "completed" : "completedlight") :
-                        t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Actual, Interval(day).firstDay())
-                         ? "booked" : "bookedlight")) :
-                       isSameDay(project->getNow(), day) ? "today" :
-                       isWeekend(day) ? "weekend" :
-                       project->isVacation(day) ? "vacation" :
-                       (r == 0 ? "default" : "defaultlight");
-               if (showPIDs)
-               {
-                       QString pids = r->getProjectIDs(Task::Actual,
-                                                                                       Interval(day).firstDay(), t);
-                       reportPIDs(pids, bgCol, !r->isGroup());
-               }
-               else
-                       reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellEndBufferStart(TableCellInfo* tci)
+{
+    genCell(time2user(tci->tli->task->getStartBufferEnd
+                      (tci->tli->sc) + 1, timeFormat), tci, false);
 }
 
 void
-HTMLReportElement::weeklyResourcePlan(const Resource* r, const Task* t)
+HTMLReportElement::genCellDuration(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    genCell(scaledDuration(tci->tli->task->getCalcDuration(tci->tli->sc),
+                           tci->tcf->realFormat),
+            tci, false);
+}
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+void
+HTMLReportElement::genCellEffort(TableCellInfo* tci)
+{
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Task)
+    {
+        val = tci->tli->task->getLoad(tci->tli->sc, Interval(start, end),
+                                      tci->tli->resource);
+    }
+    else if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        val = tci->tli->resource->getEffectiveLoad
+            (tci->tli->sc, Interval(start, end), AllAccounts, tci->tli->task);
+    }
 
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
-                week = sameTimeNextWeek(week))
-       {
-               double load =
-                       r->getLoad(Task::Plan, 
-                                          Interval(week).firstWeek(weekStartsMonday), t);
-               QString bgCol =
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" : "bookedlight") :
-                       isSameWeek(project->getNow(), week, weekStartsMonday) ? "today" :
-                       (t == 0 ? "default" : "defaultlight");
-               if (showPIDs)
-               {
-                       QString pids =
-                               r->getProjectIDs(Task::Plan, Interval(week).
-                                                                firstWeek(weekStartsMonday), t);
-                       reportPIDs(pids, bgCol, !r->isGroup());
-               }
-               else
-                       reportLoad(load, bgCol, !r->isGroup());
-       }
+    generateRightIndented(tci, scaledLoad(val, tci->tcf->realFormat));
 }
 
 void
-HTMLReportElement::weeklyResourceActual(const Resource* r, const Task* t)
+HTMLReportElement::genCellFreeLoad(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        val = tci->tli->resource->getEffectiveFreeLoad
+            (tci->tli->sc, Interval(start, end));
+    }
 
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
-                week = sameTimeNextWeek(week))
-       {
-               double load = 
-                       r->getLoad(Task::Actual, 
-                                          Interval(week).firstWeek(weekStartsMonday), t);
-               QString bgCol =
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" :
-                        (t->isCompleted(Task::Plan, sameTimeNextWeek(week) - 1) ?
-                         "completedlight" : "bookedlight")) :
-                       isSameWeek(project->getNow(), week, weekStartsMonday) ? "today" :
-                       (t == 0 ? "default" : "defaultlight");
-               if (showPIDs)
-               {
-                       QString pids = r->getProjectIDs(Task::Actual, Interval(week).
-                                                                                       firstWeek(weekStartsMonday), t);
-                       reportPIDs(pids, bgCol, !r->isGroup());
-               }
-               else
-                       reportLoad(load, bgCol, !r->isGroup());
-       }
+    generateRightIndented(tci, scaledLoad(val, tci->tcf->realFormat));
 }
 
-void 
-HTMLReportElement::weeklyTaskPlan(const Task* t, const Resource* r)
+void
+HTMLReportElement::genCellUtilization(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        double load = tci->tli->resource->getEffectiveLoad
+            (tci->tli->sc, Interval(start, end));
+        if (load > 0.0)
+        {
+            double availableLoad =
+                tci->tli->resource->getEffectiveFreeLoad
+                (tci->tli->sc, Interval(start, end));
+
+            val = 100.0 / (1.0 + availableLoad / load);
+        }
+    }
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+    generateRightIndented(tci, QString().sprintf("%.1f%%", val));
+}
 
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
-                week = sameTimeNextWeek(week))
-       {
-               double load = t->getLoad(Task::Plan, Interval(week).
-                                                                firstWeek(weekStartsMonday), r);
-               QString bgCol = 
-                       t->isActive(Task::Plan, 
-                                               Interval(week).firstWeek(weekStartsMonday)) ?
-                       (t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Plan, Interval(week).
-                                                                        firstWeek(weekStartsMonday))
-                         ? "booked" : "bookedlight")) :
-                       isSameWeek(project->getNow(), week, weekStartsMonday) ? "today" :
-                       (r == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellCriticalness(TableCellInfo* tci)
+{
+    generateRightIndented
+        (tci, scaledLoad(tci->tli->task->getCriticalness(tci->tli->sc),
+                         tci->tcf->realFormat));
 }
 
 void
-HTMLReportElement::weeklyTaskActual(const Task* t, const Resource* r)
+HTMLReportElement::genCellPathCriticalness(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    generateRightIndented
+        (tci, scaledLoad(tci->tli->task->getPathCriticalness(tci->tli->sc),
+                         tci->tcf->realFormat));
+}
 
-       for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
-                week = sameTimeNextWeek(week))
-       {
-               double load = t->getLoad(Task::Actual, Interval(week).
-                                                                firstWeek(weekStartsMonday), r);
-               QString bgCol = 
-                       t->isActive(Task::Actual,
-                                               Interval(week).firstWeek(weekStartsMonday)) ?
-                       (t->isCompleted(Task::Plan, sameTimeNextWeek(week) - 1) ?
-                        (r == 0 ? "completed" : "completedlight") :
-                        t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Actual, Interval(week).
-                                                                                  firstWeek(weekStartsMonday))
-                         ? "booked" : "bookedlight")) :
-                       isSameWeek(project->getNow(), week, weekStartsMonday) ? "today" :
-                       (r == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellProjectId(TableCellInfo* tci)
+{
+    genCell(tci->tli->task->getProjectId() + " (" +
+            report->getProject()->getIdIndex(tci->tli->task->
+                                             getProjectId()) + ")", tci,
+            true);
 }
 
 void
-HTMLReportElement::monthlyResourcePlan(const Resource* r, const Task* t)
+HTMLReportElement::genCellProjectIDs(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    genCell(tci->tli->resource->getProjectIDs(tci->tli->sc,
+                                              Interval(start, end)), tci, true);
+}
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+void
+HTMLReportElement::genCellResources(TableCellInfo* tci)
+{
+    QString text;
+    for (ResourceListIterator rli(tci->tli->task->
+                                  getBookedResourcesIterator(tci->tli->sc));
+        *rli != 0; ++rli)
+    {
+        if (!text.isEmpty())
+            text += ", ";
+
+        text += (*rli)->getName();
+    }
+    genCell(text, tci, false);
+}
 
-       for (time_t month = beginOfMonth(start); month < end;
-                month = sameTimeNextMonth(month))
-       {
-               double load = r->getLoad(Task::Plan, Interval(month).firstMonth(), t);
-               QString bgCol =
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" : "bookedlight") :
-                       isSameMonth(project->getNow(), month) ? "today" :
-                       (t == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !r->isGroup());
-       }
+void
+HTMLReportElement::genCellResponsible(TableCellInfo* tci)
+{
+    if (tci->tli->task->getResponsible())
+        genCell(tci->tli->task->getResponsible()->getName(),
+                tci, true);
+    else
+        genCell("", tci, true);
 }
 
 void
-HTMLReportElement::monthlyResourceActual(const Resource* r, const Task* t)
+HTMLReportElement::genCellText(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    if (tci->tcf->getId() == "note")
+    {
+        if (tci->tli->task->getNote().isEmpty())
+            genCell("", tci, true);
+        else
+            genCell(tci->tli->task->getNote(), tci, true);
+        return;
+    }
 
-       for (time_t month = beginOfMonth(start); month < end;
-                month = sameTimeNextMonth(month))
-       {
-               double load = r->getLoad(Task::Actual, Interval(month).firstMonth(), t);
-               QString bgCol =
-                       load > r->getMinEffort() * r->getEfficiency() ?
-                       (t == 0 ? "booked" :
-                        (t->isCompleted(Task::Plan, sameTimeNextMonth(month) - 1) ?
-                         "completedlight" : "bookedlight")) :
-                       isSameMonth(project->getNow(), month) ? "today" :
-                       (t == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !r->isGroup());
-       }
+    const TextAttribute* ta = static_cast<const TextAttribute*>
+        (tci->tli->ca1->getCustomAttribute(tci->tcf->getId()));
+    if (!ta || ta->getText().isEmpty())
+        genCell("", tci, true);
+    else
+        genCell(ta->getText(), tci, true);
 }
 
 void
-HTMLReportElement::monthlyTaskPlan(const Task* t, const Resource* r)
+HTMLReportElement::genCellStatusNote(TableCellInfo* tci)
 {
-       if (hidePlan)
-               return;
+    if (tci->tli->task->getStatusNote(tci->tli->sc).isEmpty())
+        genCell("", tci, true);
+    else
+        genCell(tci->tli->task->getStatusNote(tci->tli->sc),
+                tci, true);
+}
 
-       if (showActual)
-               s << "<td class=\"headersmall\">Plan</td>" << endl;
+void
+HTMLReportElement::genCellCost(TableCellInfo* tci)
+{
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Task)
+    {
+        val = tci->tli->task->getCredits(tci->tli->sc, Interval(start, end),
+                                       Cost, tci->tli->resource);
+    }
+    else if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        val = tci->tli->resource->getCredits(tci->tli->sc, Interval(start, end),
+                                        Cost, tci->tli->task);
+    }
+    generateRightIndented(tci, tci->tcf->realFormat.format(val, tci));
+}
 
-       for (time_t month = beginOfMonth(start); month < end;
-                month = sameTimeNextMonth(month))
-       {
-               double load = t->getLoad(Task::Plan, Interval(month).firstMonth(), r);
-               QString bgCol = 
-                       t->isActive(Task::Plan, Interval(month).firstMonth()) ?
-                       (t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Plan, Interval(month).firstMonth())
-                         ? "booked" : "bookedlight")) :
-                       isSameMonth(project->getNow(), month) ? "today" :
-                       (r == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellRevenue(TableCellInfo* tci)
+{
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Task)
+    {
+        val = tci->tli->task->getCredits(tci->tli->sc, Interval(start, end),
+                                       Revenue, tci->tli->resource);
+    }
+    else if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        val = tci->tli->resource->getCredits(tci->tli->sc, Interval(start, end),
+                                        Revenue, tci->tli->task);
+    }
+    generateRightIndented(tci, tci->tcf->realFormat.format(val, tci));
 }
 
 void
-HTMLReportElement::monthlyTaskActual(const Task* t, const Resource* r)
+HTMLReportElement::genCellProfit(TableCellInfo* tci)
 {
-       if (!hidePlan)
-               s << "<td class=\"headersmall\">Actual</td>" << endl;
+    double val = 0.0;
+    if (tci->tli->ca1->getType() == CA_Task)
+    {
+        val = tci->tli->task->getCredits(tci->tli->sc, Interval(start, end),
+                                    Revenue, tci->tli->resource) -
+            tci->tli->task->getCredits(tci->tli->sc, Interval(start, end),
+                                  Cost, tci->tli->resource);
+    }
+    else if (tci->tli->ca1->getType() == CA_Resource)
+    {
+        val = tci->tli->resource->getCredits(tci->tli->sc, Interval(start, end),
+                                        Revenue, tci->tli->task) -
+            tci->tli->resource->getCredits(tci->tli->sc, Interval(start, end),
+                                      Cost, tci->tli->task);
+    }
+    generateRightIndented(tci, tci->tcf->realFormat.format(val, tci));
+}
 
-       for (time_t month = beginOfMonth(start); month < end;
-                month = sameTimeNextMonth(month))
-       {
-               double load = t->getLoad(Task::Actual, Interval(month).firstMonth(), r);
-               QString bgCol = 
-                       t->isActive(Task::Actual, Interval(month).firstMonth()) ?
-                       (t->isCompleted(Task::Plan, sameTimeNextMonth(month) - 1) ?
-                        (r == 0 ? "completed" : "completedlight"):
-                        t->isMilestone() ? "milestone" :
-                        (r == 0 && !t->isBuffer(Task::Actual, 
-                                                                        Interval(month).firstMonth())
-                         ? "booked" : "bookedlight")) :
-                       isSameMonth(project->getNow(), month) ? "today" :
-                       (r == 0 ? "default" : "defaultlight");
-               reportLoad(load, bgCol, !t->isContainer());
-       }
+void
+HTMLReportElement::genCellPriority(TableCellInfo* tci)
+{
+    genCell(QString().sprintf("%d", tci->tli->task->getPriority()),
+            tci, true);
 }
 
 void
-HTMLReportElement::taskName(const Task* t, const Resource* r, bool big)
+HTMLReportElement::genCellFlags(TableCellInfo* tci)
 {
-       QString spaces;
-       int fontSize = big ? 100 : 90; 
-       if (resourceSortCriteria[0] == CoreAttributesList::TreeMode)
-               for (const Resource* rp = r ; rp != 0; rp = rp->getParent())
-                       spaces += "&nbsp;&nbsp;&nbsp;&nbsp;";
+    FlagList allFlags = tci->tli->ca1->getFlagList();
+    QString flagStr;
+    for (QStringList::Iterator it = allFlags.begin();
+         it != allFlags.end(); ++it)
+    {
+        if (it != allFlags.begin())
+            flagStr += ", ";
+        flagStr += *it;
+    }
+    genCell(flagStr, tci, true);
+}
 
-       mt.clear();
-       mt.addMacro(new Macro(KW("taskid"), t->getId(), defFileName,
-                                                 defFileLine));
+void
+HTMLReportElement::genCellCompleted(TableCellInfo* tci)
+{
+    double calcedCompletionDegree =
+        tci->tli->task->getCalcedCompletionDegree(tci->tli->sc);
+    double providedCompletionDegree =
+        tci->tli->task->getCompletionDegree(tci->tli->sc);
+
+    if (calcedCompletionDegree < 0)
+    {
+        if (calcedCompletionDegree == providedCompletionDegree)
+        {
+            genCell(QString(i18n("in progress")), tci, false);
+        }
+        else
+        {
+            genCell(QString(i18n("%1% (in progress)"))
+                    .arg((int) providedCompletionDegree),
+                    tci, false);
+        }
+    }
+    else
+    {
+        if (calcedCompletionDegree == providedCompletionDegree)
+        {
+            genCell(QString("%1%").arg((int) providedCompletionDegree),
+                    tci, false);
+        }
+        else
+        {
+            genCell(QString("%1% (%2%)")
+                    .arg((int) providedCompletionDegree)
+                    .arg((int) calcedCompletionDegree),
+                    tci, false);
+        }
+    }
+}
 
-       if (taskSortCriteria[0] == CoreAttributesList::TreeMode)
-       {
-               for (uint i = 0; i < t->treeLevel(); i++)
-                       spaces += "&nbsp;&nbsp;&nbsp;&nbsp;";
-               fontSize = fontSize + 5 * (maxDepthTaskList - 1 - t->treeLevel()); 
-               s << "<td class=\""
-                 << (r == 0 ? "task" : "tasklight") << "\" rowspan=\""
-                 << (showActual ? "2" : "1") << "\" style=\"white-space:nowrap\">"
-                 << spaces
-                 << "<span style=\"font-size:" 
-                 << QString().sprintf("%d", fontSize) << "%\">";
-               if (r == 0)
-                       s << "<a name=\"task_" << t->getId() << "\"></a>";
-               s << generateUrl(KW("taskname"), t->getName());
-               s << "</span></td>" << endl;
-       }
-       else
-       {
-               s << "<td class=\""
-                 << (r == 0 ? "task" : "tasklight") << "\" rowspan=\""
-                 << (showActual ? "2" : "1") << "\" style=\"white-space:nowrap\">"
-                 << spaces;
-               if (r == 0)
-                       s << "<a name=\"task_" << t->getFullId() << "\"></a>";
-               s << generateUrl(KW("taskname"), t->getName());
-               s << "</td>" << endl;
-       }
+void
+HTMLReportElement::genCellCompletedEffort(TableCellInfo* tci)
+{
+    double val = 0.0;
+
+    if (!tci->tli->resource && tci->tli->task->isLeaf())
+    {
+        // Task line, no resource.
+        val = tci->tli->task->getCompletedLoad(tci->tli->sc);
+    }
+    else if (tci->tli->ca2->getType() == CA_Resource &&
+             tci->tli->task && tci->tli->task->isLeaf())
+    {
+        // Task line, nested into a resource
+        const Project* project = report->getProject();
+        time_t now = project->getNow();
+        if (now < project->getStart())
+            now = project->getStart();
+        if (now > project->getEnd())
+            now = project->getEnd();
+        Interval iv = Interval(project->getStart(), now);
+        val = tci->tli->task->getLoad(tci->tli->sc, iv, tci->tli->resource);
+    }
+    else
+    {
+        genCell("", tci, false);
+        return;
+    }
+    generateRightIndented(tci, scaledLoad(val, tci->tcf->realFormat));
 }
 
 void
-HTMLReportElement::resourceName(const Resource* r, const Task* t, bool big)
+HTMLReportElement::genCellRemainingEffort(TableCellInfo* tci)
 {
-       QString spaces;
-       int fontSize = big ? 100 : 90;
-       if (taskSortCriteria[0] == CoreAttributesList::TreeMode)
-               for (const Task* tp = t; tp != 0; tp = tp->getParent())
-                       spaces += "&nbsp;&nbsp;&nbsp;&nbsp;";
+    double val = 0.0;
 
-       mt.clear();
-       mt.addMacro(new Macro(KW("resourceid"), r->getId(), defFileName,
-                                                 defFileLine));
-       
-       if (resourceSortCriteria[0] == CoreAttributesList::TreeMode)
-       {
-               for (uint i = 0; i < r->treeLevel(); i++)
-                       spaces += "&nbsp;&nbsp;&nbsp;&nbsp;";
-               fontSize = fontSize + 5 * (maxDepthResourceList - 1 - r->treeLevel());
-               s << "<td class=\""
-                 << (t == 0 ? "task" : "tasklight") << "\" rowspan=\""
-                 << (showActual ? "2" : "1") << "\" style=\"white-space:nowrap\">"
-                 << spaces
-                 << "<span style=\"font-size:" 
-                 << QString().sprintf("%d", fontSize) << "%\">";
-               if (t == 0)
-                       s << "<a name=\"resource_" << r->getId() << "\"></a>";
-               s << generateUrl(KW("resourcename"), r->getName());
-               s << "</span></td>" << endl;
-       }
-       else
-       {
-               s << "<td class=\""
-                 << (t == 0 ? "task" : "tasklight") << "\" rowspan=\""
-                 << (showActual ? "2" : "1") << "\" style=\"white-space:nowrap\">"
-                 << spaces;
-               if (t == 0)
-                       s << "<a name=\"resource_" << r->getId() << "\"></a>";
-               s << generateUrl(KW("resourcename"), r->getName());
-               s << "</td>" << endl;
-       }
+    if (!tci->tli->resource && tci->tli->task->isLeaf())
+    {
+        // Task line, no resource.
+        val = tci->tli->task->getRemainingLoad(tci->tli->sc);
+    }
+    else if (tci->tli->ca2->getType() == CA_Resource &&
+             tci->tli->task && tci->tli->task->isLeaf())
+    {
+        // Task line, nested into a resource
+        const Project* project = report->getProject();
+        time_t now = project->getNow();
+        if (now < project->getStart())
+            now = project->getStart();
+        if (now > project->getEnd())
+            now = project->getEnd();
+        Interval iv = Interval(now, project->getEnd());
+        val = tci->tli->task->getLoad(tci->tli->sc, iv, tci->tli->resource);
+    }
+    else
+    {
+        genCell("", tci, false);
+        return;
+    }
+
+    generateRightIndented(tci, scaledLoad(val, tci->tcf->realFormat));
 }
 
 void
-HTMLReportElement::scenarioResources(int sc, const Task* t, bool light)
+HTMLReportElement::genCellStatus(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" style=\"text-align:left\">"
-         << "<span style=\"font-size:100%\">";
-       bool first = TRUE;
-       for (ResourceListIterator rli(t->getBookedResourcesIterator(sc));
-               *rli != 0; ++rli)
-       {
-               if (!first)
-                       s << ", ";
-                                       
-               s << htmlFilter((*rli)->getName());
-               first = FALSE;
-       }
-       s << "</span></td>" << endl;
+    genCell(tci->tli->task->getStatusText(tci->tli->sc), tci, false);
 }
 
 void
-HTMLReportElement::generateDepends(const Task* t, bool light)
+HTMLReportElement::genCellReference(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" rowspan=\""
-         << (showActual ? "2" : "1")
-         << "\" style=\"text-align:left\"><span style=\"font-size:100%\">";
-       bool first = TRUE;
-       for (TaskListIterator tli(t->getPreviousIterator()); *tli != 0; ++tli)
-       {
-               if (!first)
-                       s << ", ";
-               else
-                       first = FALSE;
-               s << (*tli)->getId();
-       }
-       s << "</span</td>" << endl;
+    if (tci->tcf->getId() == "reference")
+    {
+        if (tci->tli->task->getReference().isEmpty())
+            genCell("", tci, true);
+        else
+        {
+            QString text ="<a href=\"" + tci->tli->task->getReference() + "\">";
+            if (tci->tli->task->getReferenceLabel().isEmpty())
+                text += htmlFilter(tci->tli->task->getReference());
+            else
+                text += htmlFilter(tci->tli->task->getReferenceLabel());
+            text += "</a>";
+            genCell(text, tci, true, false);
+        }
+        return;
+    }
+
+    const ReferenceAttribute* ra = static_cast<const ReferenceAttribute*>
+        (tci->tli->ca1->getCustomAttribute(tci->tcf->getId()));
+    if (!ra || ra->getURL().isEmpty())
+        genCell("", tci, true);
+    else
+    {
+        QString text ="<a href=\"" + ra->getURL() + "\">";
+        if (ra->getLabel().isEmpty())
+            text += htmlFilter(ra->getURL());
+        else
+            text += htmlFilter(ra->getLabel());
+        text += "</a>";
+        genCell(text, tci, true, false);
+    }
 }
 
 void
-HTMLReportElement::generateFollows(const Task* t, bool light)
+HTMLReportElement::genCellScenario(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" rowspan=\""
-         << (showActual ? "2" : "1")
-         << "\" style=\"text-align:left\">"
-               "<span style=\"font-size:100%\">";
-       bool first = TRUE;
-       for (TaskListIterator tli(t->getFollowersIterator()); *tli != 0; ++tli)
-       {
-               if (!first)
-                       s << ", ";
-               s << (*tli)->getId();
-               first = FALSE;
-       }
-       s << "</span</td>" << endl;
+    genCell(report->getProject()->getScenarioName(tci->tli->sc), tci, false);
+}
+
+#define GCDEPFOL(a, b) \
+void \
+HTMLReportElement::genCell##a(TableCellInfo* tci) \
+{ \
+    QString text; \
+    for (TaskListIterator it(tci->tli->task->get##b##Iterator()); *it != 0; \
+         ++it) \
+    { \
+        if (!text.isEmpty()) \
+            text += ", "; \
+        text += (*it)->getId(); \
+    } \
+    genCell(text, tci, true); \
+}
+
+GCDEPFOL(Depends, Previous)
+GCDEPFOL(Follows, Followers)
+
+QColor
+HTMLReportElement::selectTaskBgColor(TableCellInfo* tci, double load,
+                                     const Interval& period, bool daily)
+{
+    QColor bgCol;
+    if (tci->tli->task->isActive(tci->tli->sc, period) &&
+        ((tci->tli->resource != 0 && load > 0.0) || tci->tli->resource == 0))
+    {
+        if (tci->tli->task->isCompleted(tci->tli->sc, period.getEnd()))
+        {
+            if (tci->tli->ca2 == 0)
+                bgCol = colors.getColor("completed");
+            else
+                bgCol = colors.getColor("completed").light(130);
+        }
+        else
+        {
+            if (tci->tli->ca2 == 0 &&
+                !tci->tli->task->isBuffer(tci->tli->sc, period))
+            {
+                bgCol = colors.getColor("booked");
+            }
+            else
+            {
+                bgCol = colors.getColor("booked").light(130);
+            }
+        }
+    }
+    else if (period.contains(report->getProject()->getNow()))
+    {
+        bgCol = colors.getColor("today");
+    }
+    else if (daily && (isWeekend(period.getStart()) ||
+                       report->getProject()->isVacation(period.getStart())))
+    {
+            bgCol = colors.getColor("vacation");
+    }
+
+    return bgCol;
+}
+
+QColor
+HTMLReportElement::selectResourceBgColor(TableCellInfo* tci, double load,
+                                         const Interval& period, bool)
+{
+    QColor bgCol;
+    if ((load > tci->tli->resource->getMinEffort() *
+            tci->tli->resource->getEfficiency()) ||
+        (load == 0.0 && tci->tli->resource->isAllocated(tci->tli->sc, period)))
+    {
+        if (tci->tli->ca2 == 0)
+        {
+            bgCol = colors.getColor("booked");
+        }
+        else
+        {
+            if (tci->tli->task->isCompleted(tci->tli->sc, period.getEnd()))
+                bgCol = colors.getColor("completed").light(130);
+            else
+                bgCol = colors.getColor("booked").light(130);
+        }
+    }
+    else if (period.contains(report->getProject()->getNow()))
+    {
+        bgCol = colors.getColor("today");
+    }
+    else if (tci->tli->resource->getEffectiveLoad
+             (tci->tli->sc, period) == 0.0 &&
+             tci->tli->resource->getEffectiveFreeLoad(tci->tli->sc, period) ==
+             0.0)
+    {
+            bgCol = colors.getColor("vacation");
+    }
+
+    return bgCol;
 }
 
 void
-HTMLReportElement::generateResponsibilities(const Resource*r, bool light)
+HTMLReportElement::genCellTaskFunc(TableCellInfo* tci, bool daily,
+                                   time_t (*beginOfT)(time_t),
+                                   time_t (*sameTimeNextT)(time_t))
 {
-       s << "<td class=\""
-         << (light ? "defaultlight" : "default")
-         << "\" rowspan=\""
-         << (showActual ? "2" : "1")
-         << "\" style=\"text-align:left\">"
-               "<span style=\"font-size:100%\">";
-       bool first = TRUE;
-       for (TaskListIterator tli(project->getTaskListIterator()); *tli != 0;
-                ++tli)
-       {
-               if ((*tli)->getResponsible() == r)
-               {
-                       if (!first)
-                               s << ", ";
-                       s << (*tli)->getId();
-                       first = FALSE;
-               }
-       }
-       s << "</span></td>" << endl;
+    for (time_t t = (*beginOfT)(start); t < end; t = (*sameTimeNextT)(t))
+    {
+        Interval period = Interval(t, sameTimeNextT(t) - 1);
+        double load = tci->tli->task->getLoad(tci->tli->sc, period,
+                                              tci->tli->resource);
+        QColor bgCol = selectTaskBgColor(tci, load, period, daily);
+
+        int runLength = 1;
+        if (!tci->tli->task->isActive(tci->tli->sc, period))
+        {
+            time_t lastEndT = t;
+            for (time_t endT = sameTimeNextT(t); endT < end;
+                 endT = sameTimeNextT(endT))
+            {
+                Interval periodProbe = Interval(endT, sameTimeNextT(endT) - 1);
+                double loadProbe = tci->tli->task->getLoad(tci->tli->sc,
+                                                           periodProbe,
+                                                           tci->tli->resource);
+                QColor bgColProbe = selectTaskBgColor(tci, loadProbe,
+                                                      periodProbe, daily);
+                if (load != loadProbe || bgCol != bgColProbe)
+                    break;
+                lastEndT = endT;
+                runLength++;
+            }
+            t = lastEndT;
+        }
+        tci->setColumns(runLength);
+        tci->setBgColor(bgCol);
+
+        reportTaskLoad(load, tci, period);
+    }
 }
 
 void
-HTMLReportElement::generateSchedule(int sc, const Resource* r, const Task* t)
+HTMLReportElement::genCellResourceFunc(TableCellInfo* tci, bool daily,
+                                   time_t (*beginOfT)(time_t),
+                                   time_t (*sameTimeNextT)(time_t))
 {
-       s << "<td class=\""
-         << (t == 0 ? "default" : "defaultlight") 
-         << "\" style=\"text-align:left\">";
+    for (time_t t = beginOfT(start); t < end; t = sameTimeNextT(t))
+    {
+        Interval period = Interval(t, sameTimeNextT(t) - 1);
+        double load = tci->tli->resource->getEffectiveLoad
+            (tci->tli->sc, period, AllAccounts, tci->tli->task);
+        QColor bgCol = selectResourceBgColor(tci, load, period, daily);
+
+        int runLength = 1;
+        if (load == 0.0)
+        {
+            time_t lastEndT = t;
+            for (time_t endT = sameTimeNextT(t); endT < end;
+                 endT = sameTimeNextT(endT))
+            {
+                Interval periodProbe = Interval(endT, sameTimeNextT(endT) - 1);
+                double loadProbe = tci->tli->resource->getEffectiveLoad
+                    (tci->tli->sc, periodProbe, AllAccounts, tci->tli->task);
+                QColor bgColProbe = selectResourceBgColor(tci, loadProbe,
+                                                          periodProbe, daily);
+
+                if (load != loadProbe || bgCol != bgColProbe)
+                    break;
+                lastEndT = endT;
+                runLength++;
+            }
+            t = lastEndT;
+        }
+        tci->setColumns(runLength);
+        tci->setBgColor(bgCol);
+
+        reportResourceLoad(load, tci, period);
+    }
+}
 
-       if (r)
-       {
-               BookingList jobs = r->getJobs(sc);
-               jobs.setAutoDelete(TRUE);
-               time_t prevTime = 0;
-               Interval reportPeriod(start, end);
-               s << "<table style=\"width:150px; font-size:100%; "
-                  "text-align:left\"><tr><th style=\"width:35%\"></th>"
-                  "<th style=\"width:65%\"></th></tr>" << endl;
-               for (BookingListIterator bli(jobs); *bli != 0; ++bli)
-               {
-                       if ((t == 0 || t == (*bli)->getTask()) && 
-                               reportPeriod.overlaps(Interval((*bli)->getStart(), 
-                                                                                          (*bli)->getEnd())))
-                       {
-                               /* If the reporting interval is not more than a day, we
-                                * do not print the day since this information is most
-                                * likely given by the context of the report. */
-                               if (!isSameDay(prevTime, (*bli)->getStart()) &&
-                                       !isSameDay(start, end - 1))
-                               {
-                                       s << "<tr><td colspan=\"2\" style=\"font-size:120%\">"
-                                               << time2weekday((*bli)->getStart()) << ", "
-                                               << time2date((*bli)->getStart()) << "</td></tr>" 
-                                               << endl;
-                               }
-                               s << "<tr><td>";
-                               Interval workPeriod((*bli)->getStart(), (*bli)->getEnd());
-                               workPeriod.overlap(reportPeriod);
-                               s << time2user(workPeriod.getStart(), shortTimeFormat)
-                                       << "&nbsp;-&nbsp;"
-                                       << time2user(workPeriod.getEnd() + 1, shortTimeFormat);
-                               s << "</td><td>";
-                               if (t == 0)
-                                       s << " " << htmlFilter((*bli)->getTask()->getName());
-                               s << "</td>" << endl;
-                               prevTime = (*bli)->getStart();
-                               s << "</tr>" << endl;
-                       }
-               }
-               s << "</table>" << endl;
-       }
-       else
-               s << "&nbsp;";
+void
+HTMLReportElement::genCellAccountFunc(TableCellInfo* tci,
+                                      time_t (*beginOfT)(time_t),
+                                      time_t (*sameTimeNextT)(time_t))
+{
+    tci->tcf->realFormat = currencyFormat;
+    for (time_t t = beginOfT(start); t < end; t = sameTimeNextT(t))
+    {
+        double volume = tci->tli->account->
+            getVolume(tci->tli->sc, Interval(t, sameTimeNextT(t) - 1));
+        if ((accountSortCriteria[0] == CoreAttributesList::TreeMode &&
+             tci->tli->account->isRoot()) ||
+            (accountSortCriteria[0] != CoreAttributesList::TreeMode))
+            tci->tci->addToSum(tci->tli->sc, time2ISO(t), volume);
+        reportCurrency(volume, tci, t);
+    }
+}
 
-       s << "</td>" << endl;
+void
+HTMLReportElement::genCellDailyTask(TableCellInfo* tci)
+{
+    genCellTaskFunc(tci, true, midnight, sameTimeNextDay);
 }
 
 void
-HTMLReportElement::flagList(const CoreAttributes* c1, const CoreAttributes* c2)
+HTMLReportElement::genCellDailyResource(TableCellInfo* tci)
 {
-       FlagList allFlags = c1->getFlagList();
-       QString flagStr;
-       for (QStringList::Iterator it = allFlags.begin();
-                it != allFlags.end(); ++it)
-       {
-               if (it != allFlags.begin())
-                       flagStr += ", ";
-               flagStr += htmlFilter(*it);
-       }
-       if (flagStr.isEmpty())
-               flagStr = "&nbsp";
-       textMultiRows(flagStr, c2 != 0, "left");
+    genCellResourceFunc(tci, true, midnight, sameTimeNextDay);
 }
 
 void
-HTMLReportElement::generateTaskStatus(TaskStatus status, bool light)
+HTMLReportElement::genCellDailyAccount(TableCellInfo* tci)
 {
-       QString text;
-       switch (status)
-       {
-       case NotStarted:
-               text = "Not yet started";
-               break;
-       case InProgressLate:
-               text = "Behind schedule";
-               break;
-       case InProgress:
-               text = "Work in progress";
-               break;
-       case OnTime:
-               text = "On schedule";
-               break;
-       case InProgressEarly:
-               text = "Ahead of schedule";
-               break;
-       case Finished:
-               text = "Finished";
-               break;
-       default:
-               text = "Unknown status";
-               break;
-       }
-       textOneRow(text, light, "center");
+    genCellAccountFunc(tci, midnight, sameTimeNextDay);
 }
 
-QString
-HTMLReportElement::htmlFilter(const QString& s) const
+void
+HTMLReportElement::genCellWeeklyTask(TableCellInfo* tci)
 {
-    if (!HtmlMap)
-       {
-               HtmlMap = new QMap<Q_UINT16, QCString>;
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
+         week = sameTimeNextWeek(week))
+    {
+        Interval period = Interval(week, sameTimeNextWeek(week) - 1);
+        double load = tci->tli->task->getLoad(tci->tli->sc, period,
+                                              tci->tli->resource);
+        QColor bgCol = selectTaskBgColor(tci, load, period, false);
+
+        int runLength = 1;
+        if (!tci->tli->task->isActive(tci->tli->sc, period))
+        {
+            time_t lastEndWeek = week;
+            for (time_t endWeek = sameTimeNextWeek(week); endWeek < end;
+                 endWeek = sameTimeNextWeek(endWeek))
+            {
+                Interval periodProbe = Interval(endWeek)
+                    .firstWeek(weekStartsMonday);
+                double loadProbe = tci->tli->task->getLoad(tci->tli->sc,
+                                                           periodProbe,
+                                                           tci->tli->resource);
+                QColor bgColProbe = selectTaskBgColor(tci, loadProbe,
+                                                      periodProbe, false);
+                if (load != loadProbe || bgCol != bgColProbe)
+                    break;
+                lastEndWeek = endWeek;
+                runLength++;
+            }
+            week = lastEndWeek;
+        }
+        tci->setColumns(runLength);
+        tci->setBgColor(bgCol);
+
+        reportTaskLoad(load, tci, period);
+    }
+}
 
-               const Entity* ent = entitylist;
-               while(ent->code)
-               {
-                       HtmlMap->insert(ent->code, ent->name);
-                       ent++;
-               }
+void
+HTMLReportElement::genCellWeeklyResource(TableCellInfo* tci)
+{
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
+         week = sameTimeNextWeek(week))
+    {
+        Interval period = Interval(week, sameTimeNextWeek(week) - 1);
+        double load = tci->tli->resource->getEffectiveLoad
+            (tci->tli->sc, period, AllAccounts, tci->tli->task);
+        QColor bgCol = selectResourceBgColor(tci, load, period, false);
+
+        int runLength = 1;
+        if (load == 0.0)
+        {
+            time_t lastEndWeek = week;
+            for (time_t endWeek = sameTimeNextWeek(week); endWeek < end;
+                 endWeek = sameTimeNextWeek(endWeek))
+            {
+                Interval periodProbe = Interval(endWeek)
+                    .firstWeek(weekStartsMonday);
+                double loadProbe = tci->tli->resource->getEffectiveLoad
+                    (tci->tli->sc, periodProbe, AllAccounts, tci->tli->task);
+                QColor bgColProbe = selectResourceBgColor(tci, loadProbe,
+                                                          periodProbe, false);
+                if (load != loadProbe || bgCol != bgColProbe)
+                    break;
+                lastEndWeek = endWeek;
+                runLength++;
+            }
+            week = lastEndWeek;
+        }
+        tci->setColumns(runLength);
+        tci->setBgColor(bgCol);
+
+        reportResourceLoad(load, tci, period);
     }
-       
-       QString out;
-       bool parTags = FALSE;
-       for (uint i = 0; i < s.length(); i++)
-       {
-               QString repl;
-               if (HtmlMap->find(s[i]) != HtmlMap->end())
-                       repl = QString("&") + QString(*(HtmlMap->find(s[i]))) + ";";
-               else if (s.mid(i, 2) == "\n\n")
-               {
-                       repl = "</p><p>";
-                       parTags = TRUE;
-                       i++;
-               }
-
-               if (repl.isEmpty())
-                       out += s[i];
-               else
-                       out += repl;
-       }
+}
 
-       return parTags ? QString("<p>") + out + "</p>" : out;
+void
+HTMLReportElement::genCellWeeklyAccount(TableCellInfo* tci)
+{
+    bool weekStartsMonday = report->getWeekStartsMonday();
+    for (time_t week = beginOfWeek(start, weekStartsMonday); week < end;
+         week = sameTimeNextWeek(week))
+    {
+        double volume = tci->tli->account->
+            getVolume(tci->tli->sc, Interval(week, sameTimeNextWeek(week) - 1));
+        if ((accountSortCriteria[0] == CoreAttributesList::TreeMode &&
+             tci->tli->account->isRoot()) ||
+            (accountSortCriteria[0] != CoreAttributesList::TreeMode))
+            tci->tci->addToSum(tci->tli->sc, time2ISO(week), volume);
+        reportCurrency(volume, tci, week);
+    }
 }
 
 void
-HTMLReportElement::reportLoad(double load, const QString& bgCol, bool bold)
+HTMLReportElement::genCellMonthlyTask(TableCellInfo* tci)
 {
-       if (load > 0.0 && barLabels != BLT_EMPTY)
-       {
-               s << "<td class=\""
-                 << bgCol << "\">";
-               if (bold)
-                       s << "<b>";
-               s << scaledLoad(load);
-               if (bold)
-                       s << "</b>";
-               s << "</td>" << endl;
-       }
-       else
-               s << "<td class=\""
-                 << bgCol << "\">&nbsp;</td>" << endl;
+    genCellTaskFunc(tci, false, beginOfMonth, sameTimeNextMonth);
 }
 
 void
-HTMLReportElement::reportPIDs(const QString& pids, const QString bgCol, bool bold)
+HTMLReportElement::genCellMonthlyResource(TableCellInfo* tci)
 {
-       s << "<td class=\""
-         << bgCol << "\" style=\"white-space:nowrap\">";
-       if (bold)
-               s << "<b>";
-       s << pids;
-       if (bold)
-               s << "</b>";
-       s << "</td>" << endl;
+    genCellResourceFunc(tci, false, beginOfMonth, sameTimeNextMonth);
 }
 
-bool
-HTMLReportElement::setUrl(const QString& key, const QString& url)
+void
+HTMLReportElement::genCellMonthlyAccount(TableCellInfo* tci)
 {
-       if (urls.find(key) == urls.end())
-               return FALSE;
+    genCellAccountFunc(tci, beginOfMonth, sameTimeNextMonth);
+}
 
-       urls[key] = url;
-       return TRUE;
+void
+HTMLReportElement::genCellQuarterlyTask(TableCellInfo* tci)
+{
+    genCellTaskFunc(tci, false, beginOfQuarter, sameTimeNextQuarter);
 }
 
-const QString*
-HTMLReportElement::getUrl(const QString& key) const
+void
+HTMLReportElement::genCellQuarterlyResource(TableCellInfo* tci)
 {
-       if (urls.find(key) == urls.end() || urls[key] == "")
-               return 0;
-       return &urls[key];
+    genCellResourceFunc(tci, false, beginOfQuarter, sameTimeNextQuarter);
 }
 
-QString
-HTMLReportElement::generateUrl(const QString& key, const QString& txt)
+void
+HTMLReportElement::genCellQuarterlyAccount(TableCellInfo* tci)
 {
-       if (getUrl(key))
-       {
-               mt.setLocation(defFileName, defFileLine);
-               return QString("<a href=\"") + mt.expand(*getUrl(key))
-                       + "\">" + htmlFilter(txt) + "</a>";
-       }
-       else
-               return htmlFilter(txt);
+    genCellAccountFunc(tci, beginOfQuarter, sameTimeNextQuarter);
+}
+
+void
+HTMLReportElement::genCellYearlyTask(TableCellInfo* tci)
+{
+    genCellTaskFunc(tci, false, beginOfYear, sameTimeNextYear);
+}
+
+void
+HTMLReportElement::genCellYearlyResource(TableCellInfo* tci)
+{
+    genCellResourceFunc(tci, false, beginOfYear, sameTimeNextYear);
+}
+
+void
+HTMLReportElement::genCellYearlyAccount(TableCellInfo* tci)
+{
+    genCellAccountFunc(tci, beginOfYear, sameTimeNextYear);
+}
+
+void
+HTMLReportElement::genCellResponsibilities(TableCellInfo* tci)
+{
+    QString text;
+    for (TaskListIterator it(report->getProject()->getTaskListIterator());
+         *it != 0; ++it)
+    {
+        if ((*it)->getResponsible() == tci->tli->resource)
+        {
+            if (!text.isEmpty())
+                text += ", ";
+            text += (*it)->getId();
+        }
+    }
+    genCell(text, tci, true);
+}
+
+void
+HTMLReportElement::genCellScheduling(TableCellInfo* tci)
+{
+    genCell(tci->tli->task->getSchedulingText(), tci, true);
+}
+
+void
+HTMLReportElement::genCellSchedule(TableCellInfo* tci)
+{
+    s() << "   <td>" << endl;
+
+    if (tci->tli->resource)
+    {
+        BookingList jobs = tci->tli->resource->getJobs(tci->tli->sc);
+        jobs.setAutoDelete(true);
+        time_t prevTime = 0;
+        Interval reportPeriod(start, end);
+        s() << "    <table style=\"width:150px; font-size:100%; "
+           << "text-align:left\">" << endl
+           << "      <tr>" << endl
+           << "       <th style=\"width:35%\"></th>" << endl
+           << "       <th style=\"width:65%\"></th>" << endl
+           << "      </tr>" << endl;
+        for (BookingList::Iterator bli(jobs); *bli != 0; ++bli)
+        {
+            if ((tci->tli->ca2 == 0 || tci->tli->task == (*bli)->getTask()) &&
+                reportPeriod.overlaps(Interval((*bli)->getStart(),
+                                               (*bli)->getEnd())))
+            {
+                /* If the reporting interval is not more than a day, we
+                 * do not print the day since this information is most
+                 * likely given by the context of the report. */
+                if (!isSameDay(prevTime, (*bli)->getStart()) &&
+                    !isSameDay(start, end - 1))
+                {
+                    s() << "      <tr>" << endl
+                        << "       <td colspan=\"2\" style=\"font-size:120%\">"
+                        << time2weekday((*bli)->getStart()) << ", "
+                        << time2date((*bli)->getStart()) << "</td>" << endl
+                        << "      </tr>"
+                        << endl;
+                }
+                s() << "       <tr>" << endl
+                    << "        <td>";
+                Interval workPeriod((*bli)->getStart(), (*bli)->getEnd());
+                workPeriod.overlap(reportPeriod);
+                s() << time2user(workPeriod.getStart(), shortTimeFormat)
+                    << "&#160;-&#160;"
+                    << time2user(workPeriod.getEnd() + 1, shortTimeFormat);
+                s() << "</td>" << endl
+                    << "       <td>";
+                if (tci->tli->ca2 == 0)
+                    s() << " " << htmlFilter((*bli)->getTask()->getName());
+                s() << "       </td>" << endl;
+                prevTime = (*bli)->getStart();
+                s() << "      </tr>" << endl;
+            }
+        }
+        s() << "     </table>" << endl;
+    }
+    else
+        s() << "&#160;";
+
+    s() << "   </td>" << endl;
+}
+
+#define GCEFFORT(a) \
+void \
+HTMLReportElement::genCell##a##Effort(TableCellInfo* tci) \
+{ \
+    genCell(tci->tcf->realFormat.format \
+            (tci->tli->resource->get##a##Effort(), false), \
+            tci, true); \
+}
+
+GCEFFORT(Min)
+
+void
+HTMLReportElement::genCellMaxEffort(TableCellInfo* tci)
+{
+    genCell(tci->tcf->realFormat.format
+            (tci->tli->resource->getLimits() ?
+             tci->tli->resource->getLimits()->getDailyMax() : 0, false),
+            tci, true);
+}
+
+void
+HTMLReportElement::genCellEfficiency(TableCellInfo* tci)
+{
+    genCell(tci->tcf->realFormat.format(tci->tli->resource->getEfficiency(),
+                                        tci), tci, true);
+}
+
+void
+HTMLReportElement::genCellRate(TableCellInfo* tci)
+{
+    genCell(tci->tcf->realFormat.format(tci->tli->resource->getRate(), tci),
+            tci, true);
+}
+
+void
+HTMLReportElement::genCellTotal(TableCellInfo* tci)
+{
+    double value = tci->tli->account->getVolume(tci->tli->sc,
+                                                Interval(start, end));
+    if (tci->tli->account->isLeaf())
+        tci->tci->addToSum(tci->tli->sc, "total", value);
+    genCell(tci->tcf->realFormat.format(value, tci), tci, false);
+}
+
+void
+HTMLReportElement::genCellSummary(TableCellInfo* tci)
+{
+    QMap<QString, double>::ConstIterator it;
+    const QMap<QString, double>* sum = tci->tci->getSum();
+    assert(sum != 0);
+
+    uint sc = tci->tli->sc;
+    double val = 0.0;
+    if (sum[sc].begin() != sum[sc].end())
+    {
+        for (it = sum[sc].begin(); it != sum[sc].end(); ++it)
+        {
+            if (accumulate)
+                val += *it;
+            else
+                val = *it;
+            genCell(tci->tcf->realFormat.format(val, tci), tci, false);
+        }
+    }
+    else
+    {
+        // The column counter is not set in all cases. These are always single
+        // column cases.
+        if (tci->tci->getSubColumns() > 0)
+            for (uint col = 0; col < tci->tci->getSubColumns(); ++col)
+                genCell(tci->tcf->realFormat.format(0.0, tci), tci, false);
+        else
+            genCell(tci->tcf->realFormat.format(0.0, tci), tci, false);
+    }
 }