, InterpTextInfo>(fout, styles, gdi.getTL(), yscale, xscale, offsetY, offsetX);
fout << "";
char bf1[256];
char bf2[256];
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
//fout << "Skapad av MeOS: " << bf1 << " "<< bf2 << "\n";
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "MeOS: " << bf1 << " "<< bf2 << "\n";
fout << "
\n";
fout << "\n";
fout << "\n";
}
wstring html_table_code(const wstring &in)
{
if (in.size()==0)
return L" ";
else {
return encodeXML(in);
}
}
bool sortTL_X(const TextInfo *a, const TextInfo *b)
{
return a->xp < b->xp;
}
void HTMLWriter::writeTableHTML(gdioutput &gdi,
const wstring &file,
const wstring &title,
int refreshTimeOut,
double scale) {
checkWriteAccess(file);
ofstream fout(file.c_str());
if (fout.bad())
return throw std::exception("Bad output stream");
writeTableHTML(gdi, fout, title, false, refreshTimeOut, scale);
}
void HTMLWriter::writeTableHTML(gdioutput &gdi,
ostream &fout,
const wstring &title,
bool simpleFormat,
int refreshTimeOut,
double scale) {
if (scale <= 0)
scale = 1.0;
fout << "" << endl;
fout << "\n\n";
fout << "\n";
if (refreshTimeOut > 0)
fout << "\n";
fout << "" << gdioutput::toUTF8(title) << "\n";
map< pair, pair > styles;
generateStyles(gdi, fout, scale, true, gdi.getTL(), styles);
fout << "\n";
fout << "\n";
auto &TL = gdi.getTL();
auto it = TL.begin();
int MaxX = gdi.getPageX() - 100;
map tableCoordinates;
//Get x-coordinates
while (it!=TL.end()) {
tableCoordinates[it->xp]=0;
++it;
}
int kr = 0;
map::iterator mit = tableCoordinates.begin();
while (mit != tableCoordinates.end()) {
mit->second = kr++;
++mit;
}
tableCoordinates[MaxX] = kr;
vector sizeSet(kr + 1, false);
fout << "\n";
int linecounter=0;
it=TL.begin();
vector< pair > > rows;
rows.reserve(TL.size() / 3);
vector ypRow;
int minHeight = 100000;
while (it!=TL.end()) {
int y=it->yp;
vector row;
int subnormal = 0;
int normal = 0;
int header = 0;
int mainheader = 0;
while (it!=TL.end() && it->yp==y) {
if (!gdioutput::skipTextRender(it->format)) {
row.push_back(&*it);
switch (it->getGdiFont()) {
case fontLarge:
case boldLarge:
case boldHuge:
mainheader++;
break;
case boldText:
case italicMediumPlus:
case fontMediumPlus:
header++;
break;
case fontSmall:
case italicSmall:
subnormal++;
break;
default:
normal++;
}
}
++it;
}
if (row.empty())
continue;
bool isMainHeader = mainheader > normal;
bool isHeader = (header + mainheader) > normal;
bool isSub = subnormal > normal;
sort(row.begin(), row.end(), sortTL_X);
rows.resize(rows.size() + 1);
rows.back().first = isMainHeader ? 1 : (isHeader ? 2 : (isSub ? 3 : 0));
rows.back().second.swap(row);
int last = ypRow.size();
ypRow.push_back(y);
if (last > 0) {
minHeight = min(minHeight, ypRow[last] - ypRow[last-1]);
}
}
int numMin = 0;
for (size_t gCount = 1; gCount < rows.size(); gCount++) {
int h = ypRow[gCount] - ypRow[gCount-1];
if (h == minHeight)
numMin++;
}
if (numMin == 0)
numMin = 1;
int hdrLimit = (rows.size() / numMin) <= 4 ? int(minHeight * 1.2) : int(minHeight * 1.5);
for (size_t gCount = 1; gCount + 1 < rows.size(); gCount++) {
int type = rows[gCount].first;
int lastType = gCount > 0 ? rows[gCount-1].first : 0;
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
if (type == 0 && (lastType == 1 || lastType == 2) && (nextType == 1 || nextType == 2))
continue; // No reclassify
int h = ypRow[gCount] - ypRow[gCount-1];
if (h > hdrLimit && rows[gCount].first == 0)
rows[gCount].first = 2;
}
ypRow.clear();
string lineclass;
for (size_t gCount = 0; gCount < rows.size(); gCount++) {
vector &row = rows[gCount].second;
int type = rows[gCount].first;
int lastType = gCount > 0 ? rows[gCount-1].first : 0;
int nextType = gCount + 1 < rows.size() ? rows[gCount + 1].first : 0;
vector::iterator rit;
fout << "" << endl;
if (simpleFormat) {
}
else if (type == 1) {
lineclass = " class=\"freeheader\"";
linecounter = 0;
}
else if (type == 2) {
linecounter = 0;
lineclass = " valign=\"bottom\" class=\"header\"";
}
else {
if (type == 3)
linecounter = 1;
if ((lastType == 1 || lastType == 2) && (nextType == 1 || nextType == 2) && row.size() < 3) {
lineclass = "";
}
else
lineclass = (linecounter&1) ? " class=\"e1\"" : " class=\"e0\"";
linecounter++;
}
for (size_t k=0;kxp];
if (k == 0 && thisCol != 0)
fout << "| | ";
int nextCol;
if (row.size() == k + 1)
nextCol = tableCoordinates.rbegin()->second;
else
nextCol = tableCoordinates[row[k + 1]->xp];
int colspan = nextCol - thisCol;
assert(colspan > 0);
string style;
if (row[k]->format&textRight)
style = " style=\"text-align:right\"";
if (colspan == 1 && !sizeSet[thisCol]) {
fout << " xp - row[k]->xp) : (MaxX - row[k]->xp)) << "\">";
sizeSet[thisCol] = true;
}
else if (colspan > 1)
fout << " | ";
else
fout << " | ";
gdiFonts font = row[k]->getGdiFont();
string starttag, endtag;
getStyle(styles, font, gdioutput::narrow(row[k]->font), "", starttag, endtag);
fout << starttag << gdioutput::toUTF8(html_table_code(row[k]->text)) << endtag << " | " << endl;
}
fout << "
\n";
row.clear();
}
fout << "
\n";
if (!simpleFormat) {
fout << "
";
char bf1[256];
char bf2[256];
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
wstring meos = getMeosCompectVersion();
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "MeOS "
<< gdioutput::toUTF8(meos) << ": " << bf1 << " " << bf2 << "\n";
fout << "
\n";
}
fout << "" << endl;
fout << "" << endl;
}
extern wchar_t programPath[MAX_PATH];
void HTMLWriter::enumTemplates(TemplateType type, vector &descriptionFile) {
vector res;
#ifdef _DEBUG
expandDirectory((wstring(programPath) + L".\\..\\Lists\\").c_str(), L"*.template", res);
#endif
wchar_t listpath[MAX_PATH];
getUserFile(listpath, L"");
expandDirectory(listpath, L"*.template", res);
if (exePath[0])
expandDirectory(exePath, L"*.template", res);
set tags;
tCache.clear();
TemplateInfo ti;
for (wstring &fn : res) {
ifstream file(fn);
string str;
if (getline(file, str)) {
if (str == "@MEOS EXPORT TEMPLATE" && getline(file, str)) {
vector tagName;
split(str, "@", tagName);
if (tagName.size() == 2) {
ti.tag = tagName[0];
if (!tags.insert(tagName[0]).second)
continue; // Already included
string2Wide(tagName[1], ti.name);
if (getline(file, str)) {
string2Wide(str, ti.desc);
}
ti.file = fn;
if (type == TemplateType::List)
descriptionFile.push_back(ti);
}
else {
throw meosException(L"Bad template: " + fn);
}
}
else if (str == "@MEOS PAGE" && getline(file, str)) {
vector tagName;
split(str, "@", tagName);
if (tagName.size() == 2) {
ti.tag = tagName[0];
if (!tags.insert(tagName[0]).second)
continue; // Already included
string2Wide(tagName[1], ti.name);
if (getline(file, str)) {
string2Wide(str, ti.desc);
}
ti.file = fn;
if (type == TemplateType::Page)
descriptionFile.push_back(ti);
}
else {
throw meosException(L"Bad template: " + fn);
}
}
}
}
}
const HTMLWriter &HTMLWriter::getWriter(TemplateType type, const string &tag) {
auto res = tCache.find(tag);
if (res != tCache.end()) {
return *res->second;
}
else {
vector descriptionFile;
enumTemplates(type, descriptionFile);
int ix = -1;
for (size_t k = 0; k < descriptionFile.size(); k++) {
if (descriptionFile[k].tag == tag) {
ix = k;
break;
}
}
if (ix == -1)
throw std::exception("Internal error");
shared_ptr tmpl = make_shared();
tmpl->read(descriptionFile[ix].file);
vector tagName;
split(tmpl->info, "@", tagName);
if (tagName.size() == 2)
tCache[tagName[0]] = tmpl;
return *tmpl;
}
}
string HTMLWriter::localize(const string &in) {
string out;
size_t offset = 0;
size_t pos = in.find_first_of('$', offset);
while (pos != string::npos) {
if (out.empty())
out.reserve(in.length() * 2);
size_t end = in.find_first_of('$', pos+1);
if (end != string::npos && end > pos + 2) {
wstring key = gdioutput::fromUTF8(in.substr(pos + 1, end - pos - 1));
out += in.substr(offset, pos-offset);
if (key[0] != '!')
out += gdioutput::toUTF8(lang.tl(key));
else
out += gdioutput::toUTF8(lang.tl(key.substr(1), true));
offset = end + 1;
pos = in.find_first_of('$', offset);
}
else
break;
}
if (offset == 0)
return trim(in);
out += in.substr(offset);
return trim(out);
}
void HTMLWriter::read(const wstring &fileName) {
ifstream file(fileName);
string dmy;
string *acc = &dmy;
string str;
int ok = 0 ;
const string comment = "//";
while (getline(file, str)) {
if (ok == 0 && str == "@MEOS EXPORT TEMPLATE") {
ok = 1;
continue;
}
else if (ok == 1) {
ok = 2;
info = str;
}
else if (ok == 0 && str == "@MEOS PAGE") {
ok = 3;
continue;
}
else if (ok == 3) {
ok = 4;
info = str;
acc = &page;
continue;
}
else if (str.length() > 1 && str[0] == '%')
continue; // Ignore comment
else if (str == "@HEAD")
acc = &head;
else if (str == "@DESCRIPRION")
acc = &description;
else if (str == "@OUTERPAGE")
acc = &outerpage;
else if (str == "@INNERPAGE")
acc = &innerpage;
else if (str == "@SEPARATOR")
acc = &separator;
else if (str == "@END")
acc = &end;
else {
size_t cix = str.rfind(comment);
if (cix != string::npos) {
if (cix == 0)
continue; // Comment line
else if (cix > 0 && str[cix - 1] != ':')
str = str.substr(0, cix);
}
*acc += localize(str) + "\n";
if (!(str.empty() || acc->back() == '>' || acc->back() == ';' || acc->back() == '}' || acc->back() == '{'))
*acc += " ";
}
}
}
namespace {
void replaceAll(string& str, const string& from, const string& to) {
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
}
class InterpPrintTextInfo {
public:
static int x(const PrintTextInfo &ti) {
return int(ti.xp);
}
static int y(const PrintTextInfo &ti) {
return int(ti.yp);
}
static const TextInfo &ti(const PrintTextInfo &in_ti) {
return in_ti.ti;
}
};
void HTMLWriter::generate(gdioutput &gdi,
ostream &fout,
const wstring &title,
const wstring &contentDescription,
bool respectPageBreak,
const int nRows,
const int numCol,
const int interval,
const int marginPercent,
double scale) const {
int w, h;
gdi.getTargetDimension(w, h);
string meos = "MeOS: " + gdioutput::toUTF8(getMeosCompectVersion()) + "";
int margin = (w * marginPercent) / 100;
int height = nRows * gdi.getLineHeight();
bool infPage = false;
if (nRows == 0) {
infPage = true;
height = gdi.getPageY()/numCol;
}
PageInfo pageInfo;
pageInfo.topMargin = 20;
pageInfo.scaleX = 1.0f;
pageInfo.scaleY = 1.0f;
pageInfo.leftMargin = 20;
pageInfo.bottomMargin = 30;
pageInfo.pageY = float(height - margin);
pageInfo.printHeader = false;
pageInfo.yMM2PrintC = pageInfo.xMM2PrintC = 1;
pageInfo.xMM2PrintK = 0;
pageInfo.yMM2PrintK = 0;
list rectangles;
vector pages;
pageInfo.renderPages(gdi.getTL(), rectangles, false, respectPageBreak || infPage, pages);
int numChapter = 0;
for (auto &pi : pages)
if (pi.startChapter)
numChapter++;
if (infPage && pages.size() > size_t(numCol)) {
bool respectChapter = numChapter == numCol; // If the number of chapters (linked lists) equals number of columns, respec these.
vector pagesOut;
bool startPage = true;
int ydiff = 0;
for (auto &p : pages) {
if (p.text.empty())
continue;
if (respectChapter)
startPage = p.startChapter;
else if (!pagesOut.empty() && pagesOut.back().text.back().yp + p.text.back().yp / 4 > height)
startPage = true;
if (startPage && pagesOut.size() < size_t(numCol)) {
pagesOut.push_back(move(p));
startPage = false;
ydiff = int(pagesOut.back().text.back().yp);
}
else {
for (auto &t : p.text) {
pagesOut.back().text.push_back(move(t));
pagesOut.back().text.back().yp += ydiff;
}
ydiff = int(pagesOut.back().text.back().yp);
}
}
pages.swap(pagesOut);
}
string output = head;
replaceAll(output, "@D", gdioutput::toUTF8(encodeXML(contentDescription)));
replaceAll(output, "@T", gdioutput::toUTF8(encodeXML(title)));
replaceAll(output, "@M", meos);
map, pair> styles;
{
stringstream sout;
generateStyles(gdi, sout, scale, false, gdi.getTL(), styles);
replaceAll(output, "@S", sout.str());
}
int nPage = (pages.size() + numCol - 1) / numCol;
replaceAll(output, "@N", itos(nPage));
fout << output;
int ipCounter = 1;
int opCounter = 1;
for (size_t pix = 0; pix < pages.size();) {
string innerpageoutput;
for (int ip = 0; ip < numCol; ip++) {
if (pages.size() == pix)
break;
if (ip > 0) {
// Separator
output = separator;
replaceAll(output, "@P", itos(ipCounter));
replaceAll(output, "@L", itos((ip * 100) / numCol));
innerpageoutput += output;
}
auto &p = pages[pix++];
stringstream sout;
double yscale = 1.3 * scale;
double xscale = 1.2 * scale;
int offsetY = 0, offsetX = 0;
formatTL, InterpPrintTextInfo>(sout, styles, p.text, yscale, xscale, offsetY, offsetX);
output = innerpage;
replaceAll(output, "@P", itos(ipCounter++));
replaceAll(output, "@L", itos((ip * 100) / numCol));
replaceAll(output, "@C", sout.str());
replaceAll(output, "@M", meos);
innerpageoutput += output;
}
string outeroutput = outerpage;
replaceAll(outeroutput, "@P", itos(opCounter++));
replaceAll(outeroutput, "@C", innerpageoutput);
replaceAll(output, "@M", meos);
replaceAll(output, "@N", itos(nPage));
fout << outeroutput << endl;
}
assert(opCounter - 1 == nPage);
output = end;
replaceAll(output, "@N", itos(opCounter - 1));
replaceAll(output, "@I", itos(numCol));
replaceAll(output, "@T", itos(interval));
replaceAll(output, "@M", meos);
fout << output;
}
void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak,
const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale) {
checkWriteAccess(file);
ofstream fout(file.c_str());
write(gdi, fout, title, contentsDescription, respectPageBreak, typeTag, refresh,
rows, cols, time_ms, margin, scale);
}
void HTMLWriter::write(gdioutput &gdi, ostream &fout, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak, const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale) {
if (typeTag == "table")
writeTableHTML(gdi, fout, title, false, refresh, scale);
else if (typeTag == "free") {
writeHTML(gdi, fout, title, refresh, scale);
}
else {
/* auto res = tCache.find(typeTag);
if (res == tCache.end()) {
vector htmlTmpl;
HTMLWriter::enumTemplates(TemplateType::List, htmlTmpl);
int ix = -1;
for (size_t k = 0; k < htmlTmpl.size(); k++) {
if (htmlTmpl[k].tag == typeTag) {
ix = k;
break;
}
}
if (ix == -1)
throw std::exception("Internal error");
shared_ptr tmpl = make_shared();
tmpl->read(htmlTmpl[ix].file);
vector tagName;
split(tmpl->info, "@", tagName);
if (tagName.size() == 2)
tCache[tagName[0]] = tmpl;
tmpl->generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}
else {
res->second->generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}*/
getWriter(TemplateType::List, typeTag).generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}
}
void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title, int refresh, oListParam ¶m, const oEvent &oe) {
write(gdi, file, title, param.getContentsDescriptor(oe), param.pageBreak, param.htmlTypeTag,
refresh != 0 ? refresh : param.timePerPage / 1000, param.htmlRows, param.nColumns,
param.timePerPage, param.margin, param.htmlScale);
}
void HTMLWriter::getPage(const oEvent &oe, string &out) const {
out = page;
}