/************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2018 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "stdafx.h" #include "gdioutput.h" #include #include #include #include #include #include "meos_util.h" #include "Localizer.h" #include "gdiconstants.h" double getLocalScale(const wstring &fontName, wstring &faceName); wstring getMeosCompectVersion(); static void generateStyles(const gdioutput &gdi, ostream &fout, bool withTbl, const list &TL, map< pair, pair > &styles) { fout << "\n"; } static void getStyle(const map< pair, pair > &styles, gdiFonts font, const string &face, const string &extraStyle, string &starttag, string &endtag) { starttag.clear(); endtag.clear(); string extra; switch (font) { case boldText: case boldSmall: extra = "b"; break; case italicSmall: case italicText: case italicMediumPlus: extra = "i"; break; } pair key(font, face); map< pair, pair >::const_iterator res = styles.find(key); if (res != styles.end()) { const pair &stylePair = res->second; if (!stylePair.first.empty()) { starttag = "<" + stylePair.first; if (!stylePair.second.empty()) starttag += " class=\"" + stylePair.second + "\""; starttag += extraStyle; starttag += ">"; } if (!extra.empty()) { starttag += "<" + extra + ">"; endtag = ""; } if (!stylePair.first.empty()) { endtag += ""; } } else { string element; switch(font) { case boldHuge: element="h1"; break; case boldLarge: element="h2"; break; case fontLarge: element="h2"; break; case fontMedium: element="h3"; break; } if (!extraStyle.empty() && element.empty()) element = "div"; if (element.size()>0) { starttag = "<" + element + extraStyle + ">"; } if (!extra.empty()) { starttag += "<" + extra + ">"; endtag = ""; } if (element.size()>0) { endtag += ""; } } } bool gdioutput::writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const { checkWriteAccess(file); ofstream fout(file.c_str()); if (fout.bad()) return false; fout << "\n\n"; fout << "\n\n"; fout << "\n"; if (refreshTimeOut > 0) fout << "\n"; fout << "" << toUTF8(title) << "\n"; map< pair, pair > styles; generateStyles(*this, fout, false, TL, styles); fout << "\n"; fout << "\n"; list::const_iterator it = TL.begin(); double yscale = 1.3; double xscale = 1.2; int offsetY = 0; while (it!=TL.end()) { if (skipTextRender(it->format)) { ++it; continue; } string yp = itos(int(yscale*it->yp) + offsetY); string xp = itos(int(xscale *it->xp)); string estyle; if (it->format!=1 && it->format!=boldSmall) { if (it->format & textRight) estyle = " style=\"position:absolute;left:" + xp + "px;top:" + yp + "px\""; else estyle = " style=\"position:absolute;left:" + xp + "px;top:" + yp + "px\""; } else { if (it->format & textRight) estyle = " style=\"font-weight:bold;position:absolute;left:" + xp + "px;top:" + yp + "px\""; else estyle = " style=\"font-weight:bold;position:absolute;left:" + xp + "px;top:" + yp + "px\""; } string starttag, endtag; getStyle(styles, it->getGdiFont(), narrow(it->font), estyle, starttag, endtag); if (!it->text.empty()) fout << starttag << toUTF8(encodeXML(it->text)) << endtag << endl; if (it->format == boldLarge) { list::const_iterator next = it; ++next; if (next == TL.end() || next->yp != it->yp) offsetY += 7; } ++it; } 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 << toUTF8(lang.tl("Skapad av ")) + "MeOS: " << bf1 << " "<< bf2 << "\n"; fout << "

\n"; fout << "\n"; fout << "\n"; return false; } 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; } bool gdioutput::writeTableHTML(const wstring &file, const wstring &title, int refreshTimeOut) const { checkWriteAccess(file); ofstream fout(file.c_str()); if (fout.bad()) return false; return writeTableHTML(fout, title, false, refreshTimeOut); } bool gdioutput::writeTableHTML(ostream &fout, const wstring &title, bool simpleFormat, int refreshTimeOut) const { fout << "\n\n"; fout << "\n\n"; fout << "\n"; if (refreshTimeOut > 0) fout << "\n"; fout << "" << toUTF8(title) << "\n"; map< pair, pair > styles; generateStyles(*this, fout, true, TL, styles); fout << "\n"; fout << "\n"; list::const_iterator it = TL.begin(); 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, narrow(row[k]->font), "", starttag, endtag); fout << starttag << 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 << toUTF8(lang.tl("Skapad av ")) + "MeOS " << toUTF8(meos) << ": " << bf1 << " "<< bf2 << "\n"; fout << "


\n"; } fout << "\n"; fout << "\n"; return true; }