diff --git a/uppbox/uppweb/svn.cpp b/uppbox/uppweb/svn.cpp index 6a67813b9..2ff4f64eb 100644 --- a/uppbox/uppweb/svn.cpp +++ b/uppbox/uppweb/svn.cpp @@ -1,311 +1,312 @@ -#include "www.h" - -#define LLOG(x) - -VectorMap svndata; -Vector svnlog; - -void ParseSvnList(VectorMap &data, String &out, const String path, const String folder) { - String topicFolder; - - String line; - int pos = 0; - int newpos; - while (true) { - int linepos; - if((linepos = out.Find("kind=\"file\"", pos)) == -1) - return; - if((newpos = out.Find("", linepos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - String name = out.Mid(pos, newpos-pos); - String fullPath = AppendFileName(folder, name); - if((newpos = name.Find('.')) != -1) - name = name.Mid(0, newpos); - SvnListRev &rev = data.Add(path + name); - if((newpos = out.Find("revision=\"", linepos)) == -1) - return; - pos = newpos + strlen("revision=\""); - if((newpos = out.Find('\"', pos)) == -1) - return; - rev.revision = ScanInt(out.Mid(pos, newpos-pos)); - if((newpos = out.Find("", linepos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - rev.author = out.Mid(pos, newpos-pos); - if((newpos = out.Find("", linepos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - String time = out.Mid(pos, newpos-pos); - rev.time.year = ScanInt(time.Left(4)); - rev.time.month = ScanInt(time.Mid(5, 2)); - rev.time.day = ScanInt(time.Mid(8, 2)); - rev.time.hour = ScanInt(time.Mid(11, 2)); - rev.time.minute = ScanInt(time.Mid(14, 2)); - rev.time.second = ScanInt(time.Mid(17)); - rev.fullPath = fullPath; - } -} -void GetSvnFolder(VectorMap &data, String tppfolder) { - tppfolder = UnixPath(tppfolder); - String out = Sys("svn list \"" + tppfolder + "\" --xml --recursive --non-interactive"); - int posp = tppfolder.ReverseFind('.'); - int pos = tppfolder.ReverseFind('/', posp-1); - pos = tppfolder.ReverseFind('/', pos-1); - String topic = "topic:/" + tppfolder.Mid(pos, posp-pos) + "/"; - ParseSvnList(data, out, topic, tppfolder); -} -void GetSvnFolderDeep(VectorMap &data, const String &tppfolder) { - FindFile fftpp(AppendFileName(tppfolder, "*.tpp")); - while(fftpp) { - String name = fftpp.GetName(); - String p = AppendFileName(tppfolder, name); - if(fftpp.IsFolder()) - GetSvnFolder(data, p); - fftpp.Next(); - } - FindFile ff(AppendFileName(tppfolder, "*.*")); - while(ff) { - String name = ff.GetName(); - String p = AppendFileName(tppfolder, name); - if(ff.IsFolder()) - GetSvnFolderDeep(data, p); - ff.Next(); - } -} -void GetSvnList(VectorMap &data, const String &rootdir) { - LLOG("Querying svn for documentation metadata ..."); - GetSvnFolder(data, AppendFileName(rootdir, "uppbox/uppweb/www.tpp")); - GetSvnFolder(data, AppendFileName(rootdir, "uppbox/uppweb/gsoc.tpp")); - GetSvnFolderDeep(data, AppendFileName(rootdir, "uppsrc")); - GetSvnFolderDeep(data, AppendFileName(rootdir, "bazaar")); -} - -void ParseSvnLog(Vector &log, String& out){ - int pos = 0; - int newpos; - while (true) { - if((newpos = out.Find("revision=\"", pos)) == -1) - return; - pos = newpos + strlen("revision=\""); - if((newpos = out.Find('\"', pos)) == -1) - return; - SvnLogRev &rev = log.Add(); - rev.revision = out.Mid(pos, newpos-pos); - if((newpos = out.Find("", pos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - rev.author = out.Mid(pos, newpos-pos); - if((newpos = out.Find("", pos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - String time = out.Mid(pos, newpos-pos); - rev.time.year = ScanInt(time.Left(4)); - rev.time.month = ScanInt(time.Mid(5, 2)); - rev.time.day = ScanInt(time.Mid(8, 2)); - rev.time.hour = ScanInt(time.Mid(11, 2)); - rev.time.minute = ScanInt(time.Mid(14, 2)); - rev.time.second = ScanInt(time.Mid(17)); - if((newpos = out.Find("", pos)) == -1) - return; - pos = newpos + strlen(""); - int maxpos; - if((maxpos = out.Find("", pos)) == -1) - return; - while(true) { - if((newpos = out.Find("action=\"", pos)) == -1) - break; - if(newpos > maxpos) - break; - pos = newpos + strlen("action=\""); - if((newpos = out.Find('\"', pos)) == -1) - break; - SvnLogRev::SvnChange &chng = rev.changes.Add(); - chng.action = out.Mid(pos, newpos-pos); - if((newpos = out.Find(">", pos)) == -1) - break; - pos = newpos + strlen(">"); - if((newpos = out.Find('<', pos)) == -1) - break; - chng.path = out.Mid(pos, newpos-pos); - String p = chng.path.Mid(7);//skip "/trunk/" - int t = rev.tags.FindAdd(p.Left(p.FindFirstOf("/"))); - p = p.Mid(rev.tags[t].GetCount()+1); - rev.tags.FindAdd(p.Left(p.FindFirstOf("/"))); - } - if((newpos = out.Find("", pos)) == -1) - return; - pos = newpos + strlen(""); - if((newpos = out.Find("<", pos)) == -1) - return; - rev.msg = out.Mid(pos, newpos-pos); - if (rev.msg[0] == '.') - rev.major = false; - else - rev.major = true; - pos = newpos; - } -} - -void GetSvnLog(Vector &log, int limit) { - LLOG("Querying svn for revisions log ..."); - String out = Sys("svn log \"" + rootdir + "\" --xml --verbose --non-interactive" + - ((limit > -1) ? " --limit " + FormatInt(limit) : "")); - ParseSvnLog(log,out); -} - -String SvnChanges(Vector &log, int limit, String filter, bool major) { - String table = "{{700:800:800:2850:4232f0;g0;^t/25b4/25@(240) [s0;# [*2 Revision]]" - ":: [s0;# [*2 Date]]" - ":: [s0;# [*2 Author]]" - ":: [s0;# [*2 Description]]" - ":: [s0;# [*2 Files]]"; - for(int i = 0, c = 0; (c < limit) && (i < log.GetCount()); i++) { - if(filter != "" && svnlog[i].tags.Find(filter) < 0) - continue; - if(major && !svnlog[i].major) - continue; - c++; - table += "::t8/8b0/8@2 [s0; [^http`:`/`/code`.google`.com`/p/upp`-mirror`/source`/detail`?r`=" + svnlog[i].revision + "^2 " + svnlog[i].revision + "]]" - ":: [s0; [2 " + DeQtf(Format(svnlog[i].time, false)) + " ]]" - ":: [s0; [2 " + DeQtf(svnlog[i].author) + " ]]" - ":: [s0; [2 " + DeQtf(svnlog[i].msg) + " ]]" - ":: [s0; "; - for(int j = 0; j < log[i].changes.GetCount(); j++) - table += "[^http`:`/`/code`.google`.com`/p/upp`-mirror`/source`/diff`?r`=" + svnlog[i].revision + DeQtf("&format=side&path=") + DeQtf(svnlog[i].changes[j].path) + "^2 diff][2 " + svnlog[i].changes[j].action + " ]" - "[^http`:`/`/code`.google`.com`/p`/upp`-mirror`/source`/browse" + DeQtf(svnlog[i].changes[j].path) + "^2 " + DeQtf(svnlog[i].changes[j].path) + "]" + String(j == svnlog[i].changes.GetCount()-1 ? " " : "&"); - table+=" ]"; - } - table += " }}"; - return table; -} - -int64 GetFolderSize(String dir) { - int64 size = 0; - FindFile ff(AppendFileName(dir, "*.*")); - while(ff) { - String name = ff.GetName(); - String p = AppendFileName(dir, name); - if(ff.IsFile()) - size += ff.GetLength(); - else if(ff.IsFolder()) - size += GetFolderSize(p); - ff.Next(); - } - return size; -} - -String BytesToString(uint64 _bytes, bool units) -{ - String ret; - uint64 bytes = _bytes; - - if (bytes >= 1024) { - bytes /= 1024; - if (bytes >= 1024) { - bytes /= 1024; - if (bytes >= 1024) { - bytes /= 1024; - if (bytes >= 1024) { - bytes /= 1024; - ret = Format("%.1f %s", _bytes/(1024*1024*1024*1024.), units ? "Tb" : ""); - } else - ret = Format("%.1f %s", _bytes/(1024*1024*1024.), units ? "Gb" : ""); - } else - ret = Format("%.1f %s", _bytes/(1024*1024.), units ? "Mb" : ""); - } else - ret = Format("%.1f %s", _bytes/1024., units ? "Kb" : ""); - } else - ret << _bytes << (units ? "b" : ""); - return ret; -} - -Vector SvnBazaarList(String bazaarPath, Vector &log) { - Vector items; - - FindFile ff(AppendFileName(bazaarPath, "*.*")); - while(ff) { - String name = ff.GetName(); - if(ff.IsFolder() && name != "$.tpp" && name != ".svn") { - SvnBazaarItems &item = items.Add(); - item.name = name; - String p = AppendFileName(bazaarPath, item.name); - item.size = GetFolderSize(p); - item.authors = ""; - item.description = ""; - item.externalDependencies = ""; - item.imagePath = ""; - item.status = ""; - item.supportedOS = ""; - } - ff.Next(); - } - Vector logPackages; // Packages in log vector - logPackages.SetCount(log.GetCount()); - for (int i = 0; i < log.GetCount(); ++i) { - for (int j = 0; j < log[i].changes.GetCount(); ++j) { - String path = log[i].changes[j].path; - int ppos = path.Find("/bazaar/"); - if (ppos >= 0) { - String package; - ppos += strlen("/bazaar/"); - int endppos = path.Find("/", ppos+1); - package = path.Mid(ppos, endppos-ppos); - logPackages[i] += package + ", "; - } - } - } - for (int i = 0; i < log.GetCount(); ++i) { - String packages = logPackages[i]; - for (int j = 0; j < items.GetCount(); ++j) { - if (packages.Find(items[j].name) >= 0) { - if (IsNull(items[j].lastChange)) - items[j].lastChange = log[i].time; - else if (log[i].time > items[j].lastChange) - items[j].lastChange = log[i].time; - if (items[j].authors.Find(log[i].author) < 0) { - if (!items[j].authors.IsEmpty()) - items[j].authors = ", " + items[j].authors; - items[j].authors = log[i].author + items[j].authors; - } - } - } - } - return items; - /* - String table = "{{700:800:800:2850:4232:800:800:800:800f0;g0;^t/25b4/25@(240)" - " [s0;# [*2 Name]]" - ":: [s0;# [*2 Basic Description]]" - ":: [s0;# [*2 Authors]]" - ":: [s0;# [*2 Size]]" - ":: [s0;# [*2 Status]]" - ":: [s0;# [*2 Last Release]]" - ":: [s0;# [*2 External Dependencies]]" - ":: [s0;# [*2 Suported OS]]" - ":: [s0;# [*2 Image]]"; - for(int i = 0; i < items.GetCount(); i++) { - table += "::t8/8b0/8@2" - " [s0; [2 " + DeQtf(items[i].name) + " ]]" - ":: [s0; [2 " + DeQtf(items[i].description) + " ]]" - ":: [s0; [2 " + DeQtf(items[i].authors) + " ]]" - ":: [s0; [2 " + BytesToString(items[i].size) + " ]]" - ":: [s0; [2 " + DeQtf(items[i].status) + " ]]" - ":: [s0; [2 " + Format("%`", Date(items[i].lastChange)) + " ]]" - ":: [s0; [2 " + DeQtf(items[i].externalDependencies) + " ]]" - ":: [s0; [2 " + DeQtf(items[i].supportedOS) + " ]]" - ":: [s0; "; - } - table += " }}"; - return table;*/ -} - +#include "www.h" + +#define LLOG(x) + +VectorMap svndata; +Vector svnlog; + +void ParseSvnList(VectorMap &data, String &out, const String path, const String folder) { + RLOG("SvnList " << path); + String topicFolder; + + String line; + int pos = 0; + int newpos; + while (true) { + int linepos; + if((linepos = out.Find("kind=\"file\"", pos)) == -1) + return; + if((newpos = out.Find("", linepos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + String name = out.Mid(pos, newpos-pos); + String fullPath = AppendFileName(folder, name); + if((newpos = name.Find('.')) != -1) + name = name.Mid(0, newpos); + SvnListRev &rev = data.Add(path + name); + if((newpos = out.Find("revision=\"", linepos)) == -1) + return; + pos = newpos + strlen("revision=\""); + if((newpos = out.Find('\"', pos)) == -1) + return; + rev.revision = ScanInt(out.Mid(pos, newpos-pos)); + if((newpos = out.Find("", linepos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + rev.author = out.Mid(pos, newpos-pos); + if((newpos = out.Find("", linepos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + String time = out.Mid(pos, newpos-pos); + rev.time.year = ScanInt(time.Left(4)); + rev.time.month = ScanInt(time.Mid(5, 2)); + rev.time.day = ScanInt(time.Mid(8, 2)); + rev.time.hour = ScanInt(time.Mid(11, 2)); + rev.time.minute = ScanInt(time.Mid(14, 2)); + rev.time.second = ScanInt(time.Mid(17)); + rev.fullPath = fullPath; + } +} +void GetSvnFolder(VectorMap &data, String tppfolder) { + tppfolder = UnixPath(tppfolder); + String out = Sys("svn list \"" + tppfolder + "\" --xml --recursive --non-interactive"); + int posp = tppfolder.ReverseFind('.'); + int pos = tppfolder.ReverseFind('/', posp-1); + pos = tppfolder.ReverseFind('/', pos-1); + String topic = "topic:/" + tppfolder.Mid(pos, posp-pos) + "/"; + ParseSvnList(data, out, topic, tppfolder); +} +void GetSvnFolderDeep(VectorMap &data, const String &tppfolder) { + FindFile fftpp(AppendFileName(tppfolder, "*.tpp")); + while(fftpp) { + String name = fftpp.GetName(); + String p = AppendFileName(tppfolder, name); + if(fftpp.IsFolder()) + GetSvnFolder(data, p); + fftpp.Next(); + } + FindFile ff(AppendFileName(tppfolder, "*.*")); + while(ff) { + String name = ff.GetName(); + String p = AppendFileName(tppfolder, name); + if(ff.IsFolder()) + GetSvnFolderDeep(data, p); + ff.Next(); + } +} +void GetSvnList(VectorMap &data, const String &rootdir) { + LLOG("Querying svn for documentation metadata ..."); + GetSvnFolder(data, AppendFileName(rootdir, "uppbox/uppweb/www.tpp")); + GetSvnFolder(data, AppendFileName(rootdir, "uppbox/uppweb/gsoc.tpp")); + GetSvnFolderDeep(data, AppendFileName(rootdir, "uppsrc")); + GetSvnFolderDeep(data, AppendFileName(rootdir, "bazaar")); +} + +void ParseSvnLog(Vector &log, String& out){ + int pos = 0; + int newpos; + while (true) { + if((newpos = out.Find("revision=\"", pos)) == -1) + return; + pos = newpos + strlen("revision=\""); + if((newpos = out.Find('\"', pos)) == -1) + return; + SvnLogRev &rev = log.Add(); + rev.revision = out.Mid(pos, newpos-pos); + if((newpos = out.Find("", pos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + rev.author = out.Mid(pos, newpos-pos); + if((newpos = out.Find("", pos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + String time = out.Mid(pos, newpos-pos); + rev.time.year = ScanInt(time.Left(4)); + rev.time.month = ScanInt(time.Mid(5, 2)); + rev.time.day = ScanInt(time.Mid(8, 2)); + rev.time.hour = ScanInt(time.Mid(11, 2)); + rev.time.minute = ScanInt(time.Mid(14, 2)); + rev.time.second = ScanInt(time.Mid(17)); + if((newpos = out.Find("", pos)) == -1) + return; + pos = newpos + strlen(""); + int maxpos; + if((maxpos = out.Find("", pos)) == -1) + return; + while(true) { + if((newpos = out.Find("action=\"", pos)) == -1) + break; + if(newpos > maxpos) + break; + pos = newpos + strlen("action=\""); + if((newpos = out.Find('\"', pos)) == -1) + break; + SvnLogRev::SvnChange &chng = rev.changes.Add(); + chng.action = out.Mid(pos, newpos-pos); + if((newpos = out.Find(">", pos)) == -1) + break; + pos = newpos + strlen(">"); + if((newpos = out.Find('<', pos)) == -1) + break; + chng.path = out.Mid(pos, newpos-pos); + String p = chng.path.Mid(7);//skip "/trunk/" + int t = rev.tags.FindAdd(p.Left(p.FindFirstOf("/"))); + p = p.Mid(rev.tags[t].GetCount()+1); + rev.tags.FindAdd(p.Left(p.FindFirstOf("/"))); + } + if((newpos = out.Find("", pos)) == -1) + return; + pos = newpos + strlen(""); + if((newpos = out.Find("<", pos)) == -1) + return; + rev.msg = out.Mid(pos, newpos-pos); + if (rev.msg[0] == '.') + rev.major = false; + else + rev.major = true; + pos = newpos; + } +} + +void GetSvnLog(Vector &log, int limit) { + LLOG("Querying svn for revisions log ..."); + String out = Sys("svn log \"" + rootdir + "\" --xml --verbose --non-interactive" + + ((limit > -1) ? " --limit " + FormatInt(limit) : "")); + ParseSvnLog(log,out); +} + +String SvnChanges(Vector &log, int limit, String filter, bool major) { + String table = "{{700:800:800:2850:4232f0;g0;^t/25b4/25@(240) [s0;# [*2 Revision]]" + ":: [s0;# [*2 Date]]" + ":: [s0;# [*2 Author]]" + ":: [s0;# [*2 Description]]" + ":: [s0;# [*2 Files]]"; + for(int i = 0, c = 0; (c < limit) && (i < log.GetCount()); i++) { + if(filter != "" && svnlog[i].tags.Find(filter) < 0) + continue; + if(major && !svnlog[i].major) + continue; + c++; + table += "::t8/8b0/8@2 [s0; [^http`:`/`/code`.google`.com`/p/upp`-mirror`/source`/detail`?r`=" + svnlog[i].revision + "^2 " + svnlog[i].revision + "]]" + ":: [s0; [2 " + DeQtf(Format(svnlog[i].time, false)) + " ]]" + ":: [s0; [2 " + DeQtf(svnlog[i].author) + " ]]" + ":: [s0; [2 " + DeQtf(svnlog[i].msg) + " ]]" + ":: [s0; "; + for(int j = 0; j < log[i].changes.GetCount(); j++) + table += "[^http`:`/`/code`.google`.com`/p/upp`-mirror`/source`/diff`?r`=" + svnlog[i].revision + DeQtf("&format=side&path=") + DeQtf(svnlog[i].changes[j].path) + "^2 diff][2 " + svnlog[i].changes[j].action + " ]" + "[^http`:`/`/code`.google`.com`/p`/upp`-mirror`/source`/browse" + DeQtf(svnlog[i].changes[j].path) + "^2 " + DeQtf(svnlog[i].changes[j].path) + "]" + String(j == svnlog[i].changes.GetCount()-1 ? " " : "&"); + table+=" ]"; + } + table += " }}"; + return table; +} + +int64 GetFolderSize(String dir) { + int64 size = 0; + FindFile ff(AppendFileName(dir, "*.*")); + while(ff) { + String name = ff.GetName(); + String p = AppendFileName(dir, name); + if(ff.IsFile()) + size += ff.GetLength(); + else if(ff.IsFolder()) + size += GetFolderSize(p); + ff.Next(); + } + return size; +} + +String BytesToString(uint64 _bytes, bool units) +{ + String ret; + uint64 bytes = _bytes; + + if (bytes >= 1024) { + bytes /= 1024; + if (bytes >= 1024) { + bytes /= 1024; + if (bytes >= 1024) { + bytes /= 1024; + if (bytes >= 1024) { + bytes /= 1024; + ret = Format("%.1f %s", _bytes/(1024*1024*1024*1024.), units ? "Tb" : ""); + } else + ret = Format("%.1f %s", _bytes/(1024*1024*1024.), units ? "Gb" : ""); + } else + ret = Format("%.1f %s", _bytes/(1024*1024.), units ? "Mb" : ""); + } else + ret = Format("%.1f %s", _bytes/1024., units ? "Kb" : ""); + } else + ret << _bytes << (units ? "b" : ""); + return ret; +} + +Vector SvnBazaarList(String bazaarPath, Vector &log) { + Vector items; + + FindFile ff(AppendFileName(bazaarPath, "*.*")); + while(ff) { + String name = ff.GetName(); + if(ff.IsFolder() && name != "$.tpp" && name != ".svn") { + SvnBazaarItems &item = items.Add(); + item.name = name; + String p = AppendFileName(bazaarPath, item.name); + item.size = GetFolderSize(p); + item.authors = ""; + item.description = ""; + item.externalDependencies = ""; + item.imagePath = ""; + item.status = ""; + item.supportedOS = ""; + } + ff.Next(); + } + Vector logPackages; // Packages in log vector + logPackages.SetCount(log.GetCount()); + for (int i = 0; i < log.GetCount(); ++i) { + for (int j = 0; j < log[i].changes.GetCount(); ++j) { + String path = log[i].changes[j].path; + int ppos = path.Find("/bazaar/"); + if (ppos >= 0) { + String package; + ppos += strlen("/bazaar/"); + int endppos = path.Find("/", ppos+1); + package = path.Mid(ppos, endppos-ppos); + logPackages[i] += package + ", "; + } + } + } + for (int i = 0; i < log.GetCount(); ++i) { + String packages = logPackages[i]; + for (int j = 0; j < items.GetCount(); ++j) { + if (packages.Find(items[j].name) >= 0) { + if (IsNull(items[j].lastChange)) + items[j].lastChange = log[i].time; + else if (log[i].time > items[j].lastChange) + items[j].lastChange = log[i].time; + if (items[j].authors.Find(log[i].author) < 0) { + if (!items[j].authors.IsEmpty()) + items[j].authors = ", " + items[j].authors; + items[j].authors = log[i].author + items[j].authors; + } + } + } + } + return items; + /* + String table = "{{700:800:800:2850:4232:800:800:800:800f0;g0;^t/25b4/25@(240)" + " [s0;# [*2 Name]]" + ":: [s0;# [*2 Basic Description]]" + ":: [s0;# [*2 Authors]]" + ":: [s0;# [*2 Size]]" + ":: [s0;# [*2 Status]]" + ":: [s0;# [*2 Last Release]]" + ":: [s0;# [*2 External Dependencies]]" + ":: [s0;# [*2 Suported OS]]" + ":: [s0;# [*2 Image]]"; + for(int i = 0; i < items.GetCount(); i++) { + table += "::t8/8b0/8@2" + " [s0; [2 " + DeQtf(items[i].name) + " ]]" + ":: [s0; [2 " + DeQtf(items[i].description) + " ]]" + ":: [s0; [2 " + DeQtf(items[i].authors) + " ]]" + ":: [s0; [2 " + BytesToString(items[i].size) + " ]]" + ":: [s0; [2 " + DeQtf(items[i].status) + " ]]" + ":: [s0; [2 " + Format("%`", Date(items[i].lastChange)) + " ]]" + ":: [s0; [2 " + DeQtf(items[i].externalDependencies) + " ]]" + ":: [s0; [2 " + DeQtf(items[i].supportedOS) + " ]]" + ":: [s0; "; + } + table += " }}"; + return table;*/ +} + diff --git a/uppbox/uppweb/topic1.cpp b/uppbox/uppweb/topic1.cpp new file mode 100644 index 000000000..8daf6f99a --- /dev/null +++ b/uppbox/uppweb/topic1.cpp @@ -0,0 +1,74 @@ +#include "www.h" + +//#BLITZ_PROHIBIT + +/* +#define TOPICFILE +#include +*/ + +Topic ReadTopic0(const char *text) +{ + Topic topic; + CParser p(text); + try { + if(p.Id("topic")) { + topic.title = p.ReadString(); + p.Char(';'); + topic.text = p.GetPtr(); + return topic; + } + while(!p.IsEof()) { + if(p.Id("TITLE")) { + p.PassChar('('); + topic.title = p.ReadString(); + p.PassChar(')'); + } + else + if(p.Id("REF")) { + p.PassChar('('); + p.ReadString(); + p.PassChar(')'); + } + else + if(p.Id("TOPIC_TEXT")) { + p.PassChar('('); + topic.text << p.ReadString(); + p.PassChar(')'); + } + else + if(p.Id("COMPRESSED")) { + StringBuffer b; + b.Reserve(1024); + while(p.IsInt()) { + b.Cat(p.ReadInt()); + p.PassChar(','); + } + topic.text = b; + } + else { + topic.text << p.GetPtr(); + break; + } + } + } + catch(CParser::Error e) { + topic.text = String::GetVoid(); + topic.title = e; + } + return topic; +} + +void InitWwwTpp() +{ + String wwwtpp = AppendFileName(uppbox, "uppweb/www.tpp"); + FindFile ff(AppendFileName(wwwtpp, "*")); + static Vector data; + while(ff) { + RLOG(ff.GetName()); + Topic p = ReadTopic0(LoadFile(AppendFileName(wwwtpp, ff.GetName()))); + data.Add(p.text); + RegisterTopic__("", GetFileTitle(ff.GetName()), p.title, data.Top(), data.Top().GetCount()); + ff.Next(); + } +}; diff --git a/uppbox/uppweb/topic2.cpp b/uppbox/uppweb/topic2.cpp new file mode 100644 index 000000000..83e34cd53 --- /dev/null +++ b/uppbox/uppweb/topic2.cpp @@ -0,0 +1,6 @@ +#include "www.h" + +//#BLITZ_PROHIBIT + +#define TOPICFILE +#include diff --git a/uppbox/uppweb/uppweb.upp b/uppbox/uppweb/uppweb.upp index 71e59b640..7bba34b71 100644 --- a/uppbox/uppweb/uppweb.upp +++ b/uppbox/uppweb/uppweb.upp @@ -20,6 +20,8 @@ file svn.cpp, topictree.cpp, cpp.cpp tabsize 4, + topic1.cpp, + topic2.cpp, www.cpp, svn.tpp, gsoc.tpp, @@ -50,6 +52,5 @@ file www.t; mainconfig - "" = "GUI MT SKELETON RAINBOW", - "" = "GUI SKELETON RAINBOW"; + "" = "MT SKELETON RAINBOW"; diff --git a/uppbox/uppweb/www.cpp b/uppbox/uppweb/www.cpp index 0bdd3ca22..39596a700 100644 --- a/uppbox/uppweb/www.cpp +++ b/uppbox/uppweb/www.cpp @@ -1,1031 +1,1036 @@ -#include "www.h" -#define IMAGECLASS WWW -#define IMAGEFILE -#include -#include - -#define TFILE -#include - -#define LLOG(x) // LOG(x) - -#ifdef PLATFORM_WIN32 -String rootdir = "u:\\upp.src"; -String uppbox = rootdir + "uppbox"; -String uppsrc = rootdir + "uppsrc"; -String reference = rootdir + "reference"; -String examples = rootdir + "examples"; -String targetdir = "u:\\uppwww"; -String diffdir = "u:\\wwwupp"; -String pdfdir = "u:\\pdf"; -#else -String rootdir = "/root/upp.src"; -String uppbox = rootdir + "uppbox"; -String uppsrc = rootdir + "uppsrc"; -String reference = rootdir + "reference"; -String examples = rootdir + "examples"; -String targetdir = "/var/www"; -String diffdir = "/root/wwwupp"; -String pdfdir = "/root/pdf"; -#endif -String bazaar; -bool outPdf; -bool doSvn; - -String GetRcFile(const char *s) -{ - String f = GetDataFile(s); - if(FileExists(f)) - return f; - return GetHomeDirFile("upp.src/uppbox/uppweb/" + AsString(s)); -} - -bool ContainsAt(const String &source, const String &pattern, int pos) -{ - return pos >= 0 - && pos + pattern.GetLength() <= source.GetLength() - && 0 == memcmp(source.Begin() + pos, pattern.Begin(), pattern.GetLength()); -} - -bool StartsWith(const String &source, const String &pattern) -{ - return ContainsAt(source, pattern, 0); -} - -bool EndsWith(const String &source, const String &pattern) -{ - return ContainsAt(source, pattern, source.GetLength() - pattern.GetLength()); -} - -String ImgName(int q) -{ - return Sprintf("%di.png", q); -} - -typedef Image (*ImageFn)(); - -namespace Upp { -template<> -unsigned GetHashValue(const ::ImageFn& fn) { return (unsigned)(uintptr_t) fn; } -}; - -String GetImageSrc(ImageFn img) -{ - static Index il; - int q = il.Find(img); - if(il.Find(img) < 0) { - q = il.GetCount(); - il.Add(img); - PNGEncoder png; - png.SaveFile(AppendFileName(targetdir, ImgName(q)),(*img)()); - } - return ImgName(q); -} - -Htmls Wimg(ImageFn img) -{ - return HtmlImg(GetImageSrc(img)).Border(0); -} - -Htmls RoundFrame(Htmls data, String border, Color bg) -{ - return HtmlPackedTable().BgColor(bg).Width(-100) - .Attr("style", "border-style: solid; border-width: 1px; border-color: #" + border + ";") - / HtmlLine() / data; -} - -HtmlTag BoxWidth(int width) -{ - return HtmlPackedTable().Width(width) / HtmlLine(); -} - -Htmls BarSection(const char *txt) -{ - Htmls bar; - bar.Br(); - bar << HtmlPackedTable().BgColor(WhiteGray).Width(-100) / - (HtmlRow() / ( - HtmlCell().Width(10) / " " + - HtmlCell() / HtmlArial(8) / HtmlBold() / txt + - HtmlCell().Width(10) / " " - )); - return bar; -} - -Htmls BarCaption(const char *text) -{ - return HtmlLine() - .Width(-100) - .VCenter() - .Style("background-image: url('" + GetImageSrc(WWW::Caption) + "'); " - "border: 0px solid black;" - "padding-left:12px; padding-right:0px; " - "padding-top:1px; padding-bottom:1px;" - "color:#FFFFFF;") - / HtmlBold() / HtmlArial(8) / text; -} - -Htmls BarCaptionLang(const char *text) -{ - return HtmlLine() - .Width(20) - .VCenter() - .Style("background-image: url('" + GetImageSrc(WWW::News2) + "'); " - "border: 0px solid black;" - "padding-left:12px; padding-right:0px; " - "padding-top:1px; padding-bottom:1px;" - "color:#FFFFFF;") - / HtmlBold() / HtmlArial(8) / text; -} - -Htmls BarItem(Htmls content, const char *style) -{ - String bgStyle = "background-image: url('" + GetImageSrc(WWW::Button) + "'); "; - return HtmlLine().Width(-100).VCenter().Style(bgStyle + style) - / content; -} - -Htmls BarLink(const char *link, const char *text, bool nxt = true) -{ - String style = "border: 0px solid black; " - "padding-left:12px; padding-right:0px; " - "padding-top:6px; padding-bottom:6px;"; - if(nxt) - style += " border-top: 1px solid #6E89AE;"; - - return BarItem( HtmlLink(link).Class("l1") / text, style ); -} - -Htmls SearchBar(const char *domain) -{ - Htmls form = - HtmlForm("http://www.google.com/search", false, "GET") - .Style("margin:0px;padding:0px;") / - ( HtmlHidden("ie", "UTF-8") + - HtmlHidden("oe", "UTF-8") + - HtmlEdit("q", 15) + - HtmlHidden("domains", domain) + - HtmlHidden("sitesearch", domain) - ); - - Htmls content; - content << HtmlPackedTable().Width(-100) - / HtmlRow() / ( - HtmlCell() / Wimg(WWW::google) + - HtmlCell() / form - ); - - String style = "border: 0px solid black; " - "padding-left:6px; padding-right:0px; " - "padding-top:4px; padding-bottom:4px;"; - "border-top: 1px solid #6E89AE;"; - return BarItem(content, style); -} - -HtmlTag HtmlPadding(int p) -{ - return HtmlPackedTable().Width(-100) / - HtmlLine(); -} - -VectorMap escape; - -String QtfAsHtml(const char *qtf, Index& css, - const VectorMap& links, - const VectorMap& labels, - const String& outdir, const String& fn = Null) -{ - return EncodeHtml(ParseQTF(qtf), css, links, labels, outdir, fn, Zoom(8, 40), escape, 40); -} - -#define TOPICFILE -#include - -#define TOPICFILE -#include - -String GetText(const char *s) -{ - return GetTopic(s).text; -} - -String ChangeTopicLanguage(const String &topic, int lang) { - int pos = topic.ReverseFind('$'); - if (pos < 0) - return ""; - String langtxt = ToLower(LNGAsText(lang)); - return topic.Left(pos+1) + langtxt + topic.Mid(pos+1+langtxt.GetCount()); -} - -String GetTopicLanguage(const String &topic) { - int pos = topic.ReverseFind('$'); - if (pos < 0) - return ""; - return topic.Mid(pos+1, 5); -} - -String FormatDateRFC822(const Time& t) { - int tz = int((GetSysTime()-GetUtcTime())/60); - return Format("%s, %d %Mon %d %02d:%02d:%02d %s%04d", - DayName(DayOfWeek(t)).Left(3), - t.day,t.month,t.year, - t.hour,t.minute,t.second, - tz>0?"+":"",tz/60*100+(tz+1440)%60); -} - -void CreateRssFeed() { - String header="\n" - "\n" - "Ultimate++ svn changes\n" - "http://ultimatepp.org/\n" - "This feed offers list of commits to Ultimate++ framework svn repository\n" - ""+ FormatDateRFC822(GetSysTime()) + "\n" - "en-us\n" - "\n\n"; - - String items; - for(int i = 0; i < min(30,svnlog.GetCount()); i++){ - items+="\n" - "Revision " + svnlog[i].revision + "\n" - "http://code.google.com/p/upp-mirror/source/detail?r=" + svnlog[i].revision + "\n" - "http://code.google.com/p/upp-mirror/source/detail?r=" + svnlog[i].revision + "\n" - "" + FormatDateRFC822(svnlog[i].time) + "\n" - "\n" - " Revision:" + svnlog[i].revision + "\n" - " Description:" + svnlog[i].msg + "\n" - " Submitted:" + FormatDateRFC822(svnlog[i].time) + " by " + svnlog[i].author + "\n" - " Affected files: \n" - " \n" - "
\n"; - for(int j = 0; j < svnlog[i].changes.GetCount(); j++) - items+="" + svnlog[i].changes[j].action + " " - "" + svnlog[i].changes[j].path + "
\n"; - items+= - "
\n" - " \n" - " \n" - "]]>
\n" - "
\n\n"; - } - SaveFile(AppendFileName(targetdir, "svnchanges.xml"), header + items + "
\n
\n"); -} - -VectorMap tt; - -String Www(const char *topic, int lang, String topicLocation = "topic://uppweb/www/") -{ - String strLang = ToLower(LNGAsText(lang)); - String www = GatherTopics(tt, String().Cat() << topicLocation << topic << "$" << strLang); - if (www != "index.html") - return www; - return GatherTopics(tt, String().Cat() << topicLocation << topic << "$" << "en-us"); -} - -String FolderLinks(String package, String group, int lang) -{ - String qtf; - FindFile ff(AppendFileName(AppendFileName(AppendFileName(uppsrc, package), group + ".tpp"), "*.tpp")); - while(ff) { - if(ff.IsFile()) { - if (ff.GetName().Find("en-us") >= 0) { - String title; - String tl = "topic://" + package + '/' + group + '/' + GetFileTitle(ff.GetName()); - tl = ChangeTopicLanguage(tl, lang); - GatherTopics(tt, tl, title); - qtf << "________[^" << tl << "^ " << DeQtf(Nvl(title, tl)) << "]&"; - } - } - ff.Next(); - } - return qtf; -} - -void AddFiles(String& qtf, const String& dir, const char* ext, bool& b) -{ - FindFile ff(AppendFileName(dir, "*." + String(ext))); - while(ff) { - qtf << "[A4* " << DeQtf(ff.GetName()) << "]&&" - << CppAsQtf(LoadFile(AppendFileName(dir, ff.GetName()))) - << "&&&"; - ff.Next(); - b = true; - } -} - -struct Isort { - bool operator()(const String& a, const String& b) const - { - return ToUpper(a) < ToUpper(b); - } -}; - -String MakeExamples(const char *dir, const char *www, int language) -{ - String ttxt; - FindFile ff(AppendFileName(dir, "*.*")); - ttxt << "{{1:3 "; - bool next = false; - Vector ls; - while(ff) { - if(ff.IsFolder()) - ls.Add(ff.GetName()); - ff.Next(); - } - Sort(ls, Isort()); - for(int i = 0; i < ls.GetCount(); i++) { - String name = ls[i]; - String link = String().Cat() << www << '$' << name << "$" << ToLower(LNGAsText(language)) << ".html"; - Topic& topic = tt.Add(link); - topic.title = name; - String fn = AppendFileName( - AppendFileName( - AppendFileName(uppbox, "uppweb"), - String(www) + ".tpp" - ), - topic.title + "$" + ToLower(LNGAsText(language)) + ".tpp" - ); - String h = ReadTopic(LoadFile(fn)).text; - Package p; - p.Load(AppendFileName(AppendFileName(dir, name), name + ".upp")); - topic.text << "[R6* " << name << "]&&" << DeQtf(p.description) << "&"; - if(h.GetCount()) - topic.text << h; - topic.text << "[A2 &x, String& qtf, const char *folder, int lang) -{ - if(x.Find(folder) >= 0) - return; - x.Add(folder); - String srcdoc = FolderLinks(folder, "srcdoc", lang); - String src = FolderLinks(folder, "src", lang); - Package p; - p.Load(AppendFileName(uppsrc, AppendFileName(folder, GetFileName(folder) + ".upp"))); - if(srcdoc.GetLength() || src.GetLength()) { - qtf << "&&&[*4@b " << folder << "]&"; - if(!IsNull(p.description)) - qtf << "[2 " << p.description << "]&"; - if(srcdoc.GetCount()) { - qtf << "&[3/* " + Format(t_("Using %s"), folder) << "]&"; - qtf << srcdoc; - } - if(src.GetCount()) { - qtf << "&[3/* " << Format(t_("%s reference"), folder) << "]&"; - qtf << src; - } - } -} - -int CharFilterLbl(int c) -{ - return IsAlNum(c) ? c : '.'; -} - - -void QtfAsPdf(PdfDraw &pdf, const char *qtf) -{ - RichText txt = ParseQTF(qtf); - Size page = Size(3968, 6074); - UPP::Print(pdf, txt, page); -} - -VectorMap links; -VectorMap labels; -Htmls header, lastUpdate; - -Array bar; -Array languages; - -int GetLinkLanguage(const String &link) { - int pos = link.ReverseFind('$'); - if (pos < 0) - return 0; - int lang = LNGFromText(ToUpper(link.Mid(pos+1))); - for (int i = 0; i < languages.GetCount(); ++i) { - if (languages[i] == lang) - return i; - } - return 0; -} - -void ExportPage(int i) -{ - Index css; - String path = links.GetKey(i); - RLOG("Exporting " << path); - - int ilang = GetLinkLanguage(path); - SetLanguage(languages[ilang]); - String text = GetText(path); - int h; - h = ParseQTF(tt[i].text).GetHeight(1000); - - int isvn = svndata.Find(tt.GetKey(i)); - String qtflangs; - String googleFile; - if (isvn > -1) { - String txt = String("[2 ") + t_("Last edit by %s on %s") + ".]"; - qtflangs += Format(txt, svndata[isvn].author, Format(Date(svndata[isvn].time))); - googleFile = svndata[isvn].fullPath; - if (googleFile.GetCount() > rootdir.GetCount()) - googleFile = UnixPath(googleFile.Mid(rootdir.GetCount())); - else - googleFile = ""; - } - String strlang; - Array arrLangs; - for (int il = 0; il < languages.GetCount(); ++il) { - if (il != ilang) { - String topic = ChangeTopicLanguage(path, languages[il]); - int itopic; - if ((itopic = tt.Find(topic)) >= 0) { - if (tt[itopic].title.Find(" (translated)") < 0) { - if (!strlang.IsEmpty()) - strlang << ", "; - arrLangs.Add("[^" + links[itopic] + "^ [2 " + ToLower(GetNativeLangName(languages[il])) + "]]"); - } - } - } - } - if (arrLangs.GetCount() > 0) { - for (int i = 0; i < arrLangs.GetCount(); ++i) { - if (i == arrLangs.GetCount()-1 && i != 0) - strlang << String(" ") + t_("and") + " "; - else if (i > 0) - strlang << ", "; - strlang << arrLangs[i]; - } - } - if (!strlang.IsEmpty()) - qtflangs += Format(String("[2 ") + t_("This page is also in %s") + ".]", strlang); - if (tt[i].title.Find("How to contribute. Web page") < 0) { - String help = "topic://uppweb/www/contribweb$" + ToLower(LNGAsText(languages[ilang])); - qtflangs += " " + String("[^") + help + "^ [ htmlrep; - int posB = 0; - while (true) { - posB = page.Find("[IHTMLTEXT", posB); - if (posB < 0) - break; - int posBB = posB + (int)strlen("[IHTMLTEXT"); - int pos0 = page.ReverseFind("[", posB-1); - int posE = page.Find(";2", posBB); - String html0 = page.Mid(posBB, posE - posBB); - html0.Replace("`", ""); - htmlrep.Add(html0); - int posEE = page.Find("]&]", posE) + (int)strlen("]&]"); - - page = page.Left(pos0) + "QTFHTMLTEXT" + FormatInt(htmlrep.GetCount()-1) + page.Mid(posEE+1); - } - - page = QtfAsHtml(page, css, links, labels, targetdir, links[i]); - for (int iHtml = 0; iHtml < htmlrep.GetCount(); ++iHtml) - page.Replace(String("QTFHTMLTEXT") + FormatInt(iHtml), htmlrep[iHtml]); - - Color paper = SWhite; - if(path == "topic://uppweb/www/download$en-us") - page << LoadFile(GetRcFile("adsense3.txt")); -/* if(path == "topic://uppweb/www/index$en-us") { - for(int q = 0; q < news.GetCount(); q++) { - String n = GetText("uppweb/www_news/" + news[q]); - String h = news[q]; - int i = h.Find('$'); - if(i >= 0) - h = h.Mid(0, i); - if(h.GetLength() == 8) - h = h.Mid(0, 4) + '-' + h.Mid(4, 2) + '-' + h.Mid(6, 2); - page << "
"; - page << "
  " - << h << "

"; - page << QtfAsHtml(n, css, links, targetdir, FormatIntAlpha(q) + "_n"); - page << "
"; - } - }*/ - Color bg = Color(210, 217, 210); - Htmls footer; - footer << HtmlTable().Border(0).Width(-100) / HtmlLine() + - RoundFrame(HtmlPadding(8) / langs , "6E89AE;padding: 10px;", White); - Htmls html; - html << - HtmlPackedTable().Width(-100) / - HtmlLine().ColSpan(3) / header + - HtmlPackedTable().Width(-100) / ( - HtmlLine().ColSpan(3).BgColor(bg).Height(6) / "" + - HtmlRow() / ( - HtmlTCell().Center() / BoxWidth(160).Center() / ( - bar[GetLinkLanguage(path)] + - "
" + - LoadFile(GetRcFile("facebook.txt")) + - "

" + -// "

" + - LoadFile(GetRcFile("adsense2.txt")) + - "

" + - LoadFile(GetRcFile("adlinks.txt")) + - (h > 25000 ? "

" + LoadFile(GetRcFile("adsense2.txt")) - : "") + - "


" + -// LoadFile(GetRcFile("referral.txt")) + -// LoadFile(GetRcFile("referral2.txt")) + -// LoadFile(GetRcFile("donations.txt")) + -// "

" + -// amazon[i % amazon.GetCount()] + - "


" + - HtmlLink("http://sourceforge.net/projects/upp/") / - HtmlImg("http://sourceforge.net/sflogo.php?group_id=93970&type=2", - "SourceForge.net Logo").Border(0).Width(125).Height(37) + - "

" + - HtmlLink("http://www.sdjournal.org/en/") / - HtmlImg(GetImageSrc(WWW::Sdj)).Border(0) + - "

" + - (links[i] == "index.html" ? lastUpdate : Htmls()) + - HtmlImg("http://www.vol.cz/cgi-bin/wc/upp").Width(1).Height(1) - ) + - HtmlTCell().BgColor(bg) / BoxWidth(6) / "" + - HtmlTCell().Width(-100).BgColor(bg) / ( - RoundFrame(HtmlPadding(8) / page , "6E89AE;padding: 10px;", White) + - footer - ) - ) - ); - - String topicTitle = tt.GetKey(i); - String pageTitle = tt[i].title; - if(IsNull(pageTitle)) - pageTitle = "Ultimate++"; - if(StartsWith(topicTitle, "examples$")) - pageTitle = "Demos / " + pageTitle; - else if(StartsWith(topicTitle, "reference$")) - pageTitle = "Examples / " + pageTitle; - - if(pageTitle != "Ultimate++") - pageTitle << " :: Ultimate++"; - - Htmls content = - "\n" + - HtmlHeader(pageTitle, AsCss(css) + - "a.l1 { text-decoration:none; font-size: 8pt; font-family: sans-serif; " - "font-weight: normal; }\n" - "a.l1:link { color:#000000; }\n" - "a.l1:visited { color:#000080; }\n" - "a.l1:hover { color:#9933CC; }\n" - "a.l1:active { color:#000000; }\n" - "a.l2 { text-decoration:none; font-size: 12pt; font-family: sans-serif; " - "font-variant: small-caps; }\n" - "a.l2:link { color:#0066FF; }\n" - "a.l2:visited { color:#FF6600; }\n" - "a.l2:hover { color:#BC0624; }\n" - "a.l2:active { color:#BC0024; }\n", - "" - "\n" - "" -// "" - ) - - - .BgColor(bg) - .Alink(Red).Link(Black).Vlink(Blue) - / html; - SaveFile(AppendFileName(targetdir, links[i]), content); -} - - -struct ProgramData { - String rootdir; - String targetdir; - String diffdir; - String pdfdir; - bool ftpUpload; - bool outPdf; - bool doSvn; - void Xmlize(XmlIO xml) { - xml - ("rootdir", rootdir) - ("targetdir", targetdir) - ("diffdir", diffdir) - ("pdfdir", pdfdir) - ("ftpUpload", ftpUpload) - ("outPdf", outPdf) - ("doSvn", doSvn) - ; - } -}; - -GUI_APP_MAIN -{ -#ifdef PLATFORM_POSIX - StdLogSetup(LOG_COUT); - rootdir = GetHomeDirFile("upp.src"); - targetdir = GetHomeDirFile("uppwww"); - diffdir = GetHomeDirFile("wwwupp"); - pdfdir = GetHomeDirFile("pdf"); -#endif - outPdf = true; - doSvn = true; - - ProgramData data; - - String configFile = GetHomeDirFile("uppweb.xml"); - bool cfgloaded = false; - if (FileExists(configFile)) { - if (LoadFromXMLFile(data, configFile)) { - rootdir = data.rootdir; - targetdir = data.targetdir; - diffdir = data.diffdir; - pdfdir = data.pdfdir; -// ftpupload = data.ftpUpload; - outPdf = data.outPdf; - doSvn = data.doSvn; - cfgloaded = true; - } - } - if (!cfgloaded) { - data.rootdir = rootdir; - data.targetdir = targetdir; - data.diffdir = diffdir; - data.pdfdir = pdfdir; -// data.ftpUpload = ftpupload; - data.outPdf = outPdf; - data.doSvn = doSvn; - StoreAsXMLFile(data, NULL, configFile); - } - if (!DirectoryExists(rootdir)) { - Exclamation ("Directory " + DeQtf(rootdir) + " does not exist"); - return; - } - - uppbox = AppendFileName(rootdir, "uppbox"); - uppsrc = AppendFileName(rootdir, "uppsrc"); - reference = AppendFileName(rootdir, "reference"); - examples = AppendFileName(rootdir, "examples"); - bazaar = AppendFileName(rootdir, "bazaar"); - - languages.Add(LNG_('E','N','U','S')); // en-us has to be the first one - languages.Add(LNG_('C','A','E','S')); - languages.Add(LNG_('C','S','C','Z')); - languages.Add(LNG_('D','E','D','E')); - languages.Add(LNG_('E','S','E','S')); - languages.Add(LNG_('F','R','F','R')); - languages.Add(LNG_('R','O','R','O')); - languages.Add(LNG_('R','U','R','U')); - languages.Add(LNG_('Z','H','C','N')); - languages.Add(LNG_('Z','H','T','W')); - - RLOG("--- uppweb started at " << GetSysTime()); - - RealizeDirectory(targetdir); - - if (outPdf) { - RealizeDirectory(pdfdir); - } - GatherRefLinks(uppsrc); - GatherRefLinks(AppendFileName(rootdir, "bazaar")); - - SaveFile(AppendFileName(targetdir, "sdj.gif"), LoadFile(GetRcFile("sdj.gif"))); - - String release = "4193"; - escape.Add("RELEASE", release); - escape.Add("RELEASET", release); - escape.Add("UPDATETIME", Format("%`", GetUtcTime())); - - if (doSvn) { - GetSvnList(svndata, rootdir); - GetSvnLog(svnlog); - CreateRssFeed(); - if (svnlog.GetCount() > 0) { - escape.Add("LATESTSVN", svnlog[0].revision); - //Index css; - //escape.Add("SVNTABLE", QtfAsHtml(SvnChanges(svnlog, "", 100), css, links, labels, targetdir)); - //escape.Add("ANCHOR", ""); - } - } - - escape.Add("PAYPAL", LoadFile(GetRcFile("donations.txt"))); - - header = HtmlPackedTable() - .Width(-100) - .BgColor(White) - .Attr("style", "border: 1px solid #6E89AE;" - "padding-left: 10px;padding-right: 0px;padding-top: 0px;padding-bottom: 0px;") - / - HtmlRow() / ( - HtmlCell() / HtmlLink("index.html") / Wimg(WWW::Logo6) + - HtmlCell().Right().Bottom() - .Style("padding-bottom: 5px; " - "background-image: url('" + GetImageSrc(WWW::HB) + "')") - / HtmlArial(14) / (LoadFile(GetRcFile("adsense.txt")) + "  "/* + "
..harnessing the real power of C++  "*/) - ); - - bar.SetCount(languages.GetCount()); - - int lang = GetCurrentLanguage(); - for (int i = 0; i < languages.GetCount(); ++i) { - Htmls bi, bex, bdoc, bcom, bcon, bsearch, blang; - - SetLanguage(languages[i]); - - Www("index", languages[i]); - Www("contribweb", languages[i]); - // bi << BarLink("index.html", "Home", false); - bi << BarLink(Www("overview", languages[i]), t_("Overview"), false); - bi << BarLink(Www("examples", languages[i]), t_("Examples")); - { - int di = tt.Find("topic://uppweb/www/examples$" + ToLower(LNGAsText(languages[i]))); - tt[di].text << MakeExamples(examples, "examples", languages[i]); - tt[di].text << GetTopic("topic://uppweb/www/reference$" + ToLower(LNGAsText(languages[i]))).text; - tt[di].text << MakeExamples(reference, "reference", languages[i]); - } - - bi << BarLink(Www("ss", languages[i]), t_("Screenshots")); - bi << BarLink(Www("comparison", languages[i]), t_("Comparisons")); - bi << BarLink(Www("apps", languages[i]), t_("Applications")); - bi << BarLink(Www("download", languages[i]), t_("Download")); - - bi << BarLink(Www("documentation", languages[i]), t_("Manual")); - { - int di = tt.Find("topic://uppweb/www/documentation$" + ToLower(LNGAsText(languages[i]))); - if (di >= 0) { - Index x; - x.Clear(); - String qtf; - SrcDocs(x, qtf, "Core", languages[i]); - SrcDocs(x, qtf, "Draw", languages[i]); - SrcDocs(x, qtf, "CtrlCore", languages[i]); - SrcDocs(x, qtf, "CtrlLib", languages[i]); - SrcDocs(x, qtf, "RichText", languages[i]); - SrcDocs(x, qtf, "RichEdit", languages[i]); - FindFile ff(AppendFileName(uppsrc, "*.*")); - Array folders; - folders.Clear(); - while(ff) { - if(ff.IsFolder()) - folders.Add(ff.GetName()); - ff.Next(); - } - Sort(folders); - for (int ifold = 0; ifold < folders.GetCount(); ++ifold) - SrcDocs(x, qtf, folders[ifold], languages[i]); - tt[di].text << qtf; - } - } - bi << BarLink(Www("bazaar", languages[i]), t_("Bazaar")); - bi << BarLink(Www("Roadmap", languages[i]), t_("Status & Roadmap")); - bi << BarLink(Www("FAQ", languages[i]), t_("FAQ")); - bi << BarLink(Www("About", languages[i], "topic://ide/app/"), t_("Authors & License")); - - bi << BarLink("http://www.ultimatepp.org/forum", t_("Forums")); - // bcom << BarLink(Www("mailing"), "Mailing lists"); - // bi << BarLink("http://www.ultimatepp.org/wiki/index.php", "Wiki"); - bi << BarLink(Www("Funding", languages[i]), t_("Funding Ultimate++")); - // bcom << BarLink(Www("helpus"), "Getting involved"); - // bcom << BarLink("mailto: upp@ntllib.org", "Contact developers"); - - bsearch << BarCaption(t_("Search on this site")); - bsearch << SearchBar("www.ultimatepp.org"); - - //blang << BarCaptionLang(t_("Languages")); - //blang << BarLink(Www("English", languages[i]), t_("Bazaar")); - //blang << BarLink(Www("Russian", languages[i]), t_("Bazaar")); - - HtmlTag bf = HtmlPackedTable() - .Width(-100) - .BgColor(White) - .Attr("style", "border-style: solid; border-width: 1px; border-color: #6E89AE;" - "padding: 0px"); - String div = HtmlTable().Border(0).Width(-100) / HtmlLine(); - bar[i] = bf / bi + div + - // bf / bex + div + - // bf / bdoc + div + - // bf / bcom + div + - // bf / bcon + div + - bf / bsearch + div; - //bf / blang; - } - SetLanguage(lang); - - for(int i = 0; i < tt.GetCount(); i++) { - String topic = tt.GetKey(i); - links.Add(topic, topic == "topic://uppweb/www/index$en-us" ? "index.html" : - memcmp(topic, "topic://", 8) ? topic : TopicFileNameHtml(topic)); - } - - String svntableStr = DeQtf("[svntable]"); - for(int i = 0; i < tt.GetCount(); i++) { - if (tt[i].title == "Svn releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 300, "")); - else if (tt[i].title == "Svn Web releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppweb")); - else if (tt[i].title == "Svn Bazaar releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "bazaar")); - else if (tt[i].title == "Svn Upp releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppsrc")); - else if (tt[i].title == "Svn major releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 300, "", true)); - else if (tt[i].title == "Svn Web major releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppweb", true)); - else if (tt[i].title == "Svn Bazaar major releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "bazaar", true)); - else if (tt[i].title == "Svn Upp major releases") - tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppsrc", true)); - else if (links[i].Find("index") >= 0) { - String win32 = "upp-win32-RELEASE.exe"; - String win32release = win32; - win32release.Replace(String("RELEASE"), release); - String x11 = "upp-x11-src-RELEASE.tar.gz"; - String x11release = x11; - x11release.Replace(String("RELEASE"), release); - tt[i].text.Replace(DeQtf(x11), DeQtf(x11release)); - tt[i].text.Replace(DeQtf(win32), DeQtf(win32release)); - } - } - - for(int i = 0; i < reflink.GetCount(); i++) { - String l = reflink.GetKey(i); - String lbl = Filter(l, CharFilterLbl); - String f = links.Get(reflink[i], Null) + '#' + lbl; - links.Add(l, f); - static const char *x[] = { "::struct", "::class", "::union" }; - for(int ii = 0; ii < 3; ii++) { - String e = x[ii]; - if(EndsWith(l, e)) { - links.Add(l.Mid(0, l.GetLength() - e.GetLength()), f); - } - } - labels.Add(l, lbl); - } - - Date d = GetSysDate(); - lastUpdate = HtmlItalic() / HtmlArial(8) / HtmlFontColor(Gray()) / - (String().Cat() << "Last update " << GetSysDate()); - -// Vector amazon = Split(LoadFile(GetRcFile("amazon.txt")), '\n');//440 - - Vector bazaarItems = SvnBazaarList(bazaar, svnlog); - - // To fill Bazaar page with real release dates and size - for(int i = 0; i < tt.GetCount(); i++) { - if (tt[i].title == "Bazaar") { - String page = tt[i]; - for (int j = 0; j < bazaarItems.GetCount(); ++j) { - int pos = page.Find("2 " + DeQtf(bazaarItems[j].name) + "]]"); - if (pos < 0) - pos = page.Find("2 " + DeQtf(bazaarItems[j].name) + "\r\n]]"); - if (pos >= 0) { - pos = page.Find("::", pos); - pos = page.Find("::", pos); - pos = page.Find(":: [s0;=2", pos); - if (pos >= 0) - pos += (int)strlen(":: [s0;=2"); - String strDate; - if (pos >= 0) { - Time t = bazaarItems[j].lastChange; - if (IsNull(t)) - strDate = "Not in Svn log"; - else - strDate = Format("%Mon", t.month) + " " + FormatInt(t.year); - page.Insert(pos, " " + strDate); - } - pos = page.Find(":: [s0;=2", pos); - if (pos >= 0) - pos += (int)strlen(":: [s0;=2"); - String strSz; - if (pos >= 0) { - if (bazaarItems[j].size == 0) - strSz = "Not in Svn log"; - else - strSz = BytesToString(bazaarItems[j].size); - - page.Insert(pos, " " + strSz); - } - } - } - tt[i].text = page; - } - } - - LLOG("G: " << MemoryUsedKb()); - -/* - if (outPdf) { - PdfDraw pdf; - for(int i = 0; i < tt.GetCount(); i++) - QtfAsPdf(pdf, tt[i]); - SaveFile(AppendFileName(pdfdir, "Upp.pdf"), pdf.Finish()); - } -*/ - - LLOG("H: " << MemoryUsedKb()); - - for(int i = 0; i < tt.GetCount(); i++) - ExportPage(i); - SetLanguage(lang); - - LLOG("I: " << MemoryUsedKb()); - -// SaveFile(AppendFileName(targetdir, "favicon.ico"), LoadFile(AppendFileName(uppsrc, "ide/ide.ico"))); - SaveFile(AppendFileName(targetdir, "stats.html"), - HtmlImg("http://www.vol.cz/cgi-bin/wc/upp") + "
" + - HtmlLink("http://www.mygooglepagerank.com", "_blank") / - "" + - "" + - HtmlLink("http://www.mygooglepagerank.com", "_blank") / - "" + - "" - ); - BeepInformation(); - -#if 0 // we are now doing this on server, directly copying to www directory - - if (!ftpupload) - return; - - RLOG("uppweb Finished, now about to upload the content"); - - Vector upload; - { - FindFile ff(AppendFileName(targetdir, "*.*")); - while(ff) { - if(ff.IsFile()) { - String s = LoadFile(AppendFileName(targetdir, ff.GetName())); - String f = AppendFileName(diffdir, ff.GetName()); - if(LoadFile(f) != s) { - upload.Add(ff.GetName()); - RLOG("upload: " << ff.GetName()); - } - } - ff.Next(); - } - } - RealizeDirectory(diffdir); - - if(upload.GetCount()) { - FtpClient ftp; - RLOG("Connecting ftp..."); - if(!ftp.Connect(getenv("UPPFTP"), getenv("UPPFTPUSR"), getenv("UPPFTPPWD"), true)) { - RLOG("Unable to connect!" + ftp.GetError()); - SetExitCode(1); - return; - } - if(!ftp.Cd("www")) { - RLOG("Unable to 'cd www'"); - SetExitCode(1); - return; - } - for(int i = 0; i < upload.GetCount(); i++) { - RLOG("Uploading " << upload[i]); - String s = LoadFile(AppendFileName(targetdir, upload[i])); - if(!ftp.Save(upload[i], s)) { - RLOG("FTP error (file upload): " + ftp.GetError()); - SetExitCode(1); - return; - } - SaveFile(AppendFileName(diffdir, upload[i]), s); - } - } - BeepInformation(); -#endif -} +#include "www.h" +#define IMAGECLASS WWW +#define IMAGEFILE +#include +#include + +#define TFILE +#include + +#define LLOG(x) // LOG(x) + +#ifdef PLATFORM_WIN32 +String rootdir = "u:\\upp.src"; +String uppbox = rootdir + "uppbox"; +String uppsrc = rootdir + "uppsrc"; +String reference = rootdir + "reference"; +String examples = rootdir + "examples"; +String targetdir = "u:\\uppwww"; +String diffdir = "u:\\wwwupp"; +String pdfdir = "u:\\pdf"; +#else +String rootdir = "/root/upp.src"; +String uppbox = rootdir + "uppbox"; +String uppsrc = rootdir + "uppsrc"; +String reference = rootdir + "reference"; +String examples = rootdir + "examples"; +String targetdir = "/var/www"; +String diffdir = "/root/wwwupp"; +String pdfdir = "/root/pdf"; +#endif +String bazaar; +bool outPdf; +bool doSvn; + +String GetRcFile(const char *s) +{ + String f = GetDataFile(s); + if(FileExists(f)) + return f; + return GetHomeDirFile("upp.src/uppbox/uppweb/" + AsString(s)); +} + +bool ContainsAt(const String &source, const String &pattern, int pos) +{ + return pos >= 0 + && pos + pattern.GetLength() <= source.GetLength() + && 0 == memcmp(source.Begin() + pos, pattern.Begin(), pattern.GetLength()); +} + +bool StartsWith(const String &source, const String &pattern) +{ + return ContainsAt(source, pattern, 0); +} + +bool EndsWith(const String &source, const String &pattern) +{ + return ContainsAt(source, pattern, source.GetLength() - pattern.GetLength()); +} + +String ImgName(int q) +{ + return Sprintf("%di.png", q); +} + +typedef Image (*ImageFn)(); + +namespace Upp { +template<> +unsigned GetHashValue(const ::ImageFn& fn) { return (unsigned)(uintptr_t) fn; } +}; + +String GetImageSrc(ImageFn img) +{ + static Index il; + int q = il.Find(img); + if(il.Find(img) < 0) { + q = il.GetCount(); + il.Add(img); + PNGEncoder png; + png.SaveFile(AppendFileName(targetdir, ImgName(q)),(*img)()); + } + return ImgName(q); +} + +Htmls Wimg(ImageFn img) +{ + return HtmlImg(GetImageSrc(img)).Border(0); +} + +Htmls RoundFrame(Htmls data, String border, Color bg) +{ + return HtmlPackedTable().BgColor(bg).Width(-100) + .Attr("style", "border-style: solid; border-width: 1px; border-color: #" + border + ";") + / HtmlLine() / data; +} + +HtmlTag BoxWidth(int width) +{ + return HtmlPackedTable().Width(width) / HtmlLine(); +} + +Htmls BarSection(const char *txt) +{ + Htmls bar; + bar.Br(); + bar << HtmlPackedTable().BgColor(WhiteGray).Width(-100) / + (HtmlRow() / ( + HtmlCell().Width(10) / " " + + HtmlCell() / HtmlArial(8) / HtmlBold() / txt + + HtmlCell().Width(10) / " " + )); + return bar; +} + +Htmls BarCaption(const char *text) +{ + return HtmlLine() + .Width(-100) + .VCenter() + .Style("background-image: url('" + GetImageSrc(WWW::Caption) + "'); " + "border: 0px solid black;" + "padding-left:12px; padding-right:0px; " + "padding-top:1px; padding-bottom:1px;" + "color:#FFFFFF;") + / HtmlBold() / HtmlArial(8) / text; +} + +Htmls BarCaptionLang(const char *text) +{ + return HtmlLine() + .Width(20) + .VCenter() + .Style("background-image: url('" + GetImageSrc(WWW::News2) + "'); " + "border: 0px solid black;" + "padding-left:12px; padding-right:0px; " + "padding-top:1px; padding-bottom:1px;" + "color:#FFFFFF;") + / HtmlBold() / HtmlArial(8) / text; +} + +Htmls BarItem(Htmls content, const char *style) +{ + String bgStyle = "background-image: url('" + GetImageSrc(WWW::Button) + "'); "; + return HtmlLine().Width(-100).VCenter().Style(bgStyle + style) + / content; +} + +Htmls BarLink(const char *link, const char *text, bool nxt = true) +{ + String style = "border: 0px solid black; " + "padding-left:12px; padding-right:0px; " + "padding-top:6px; padding-bottom:6px;"; + if(nxt) + style += " border-top: 1px solid #6E89AE;"; + + return BarItem( HtmlLink(link).Class("l1") / text, style ); +} + +Htmls SearchBar(const char *domain) +{ + Htmls form = + HtmlForm("http://www.google.com/search", false, "GET") + .Style("margin:0px;padding:0px;") / + ( HtmlHidden("ie", "UTF-8") + + HtmlHidden("oe", "UTF-8") + + HtmlEdit("q", 15) + + HtmlHidden("domains", domain) + + HtmlHidden("sitesearch", domain) + ); + + Htmls content; + content << HtmlPackedTable().Width(-100) + / HtmlRow() / ( + HtmlCell() / Wimg(WWW::google) + + HtmlCell() / form + ); + + String style = "border: 0px solid black; " + "padding-left:6px; padding-right:0px; " + "padding-top:4px; padding-bottom:4px;"; + "border-top: 1px solid #6E89AE;"; + return BarItem(content, style); +} + +HtmlTag HtmlPadding(int p) +{ + return HtmlPackedTable().Width(-100) / + HtmlLine(); +} + +VectorMap escape; + +String QtfAsHtml(const char *qtf, Index& css, + const VectorMap& links, + const VectorMap& labels, + const String& outdir, const String& fn = Null) +{ + return EncodeHtml(ParseQTF(qtf), css, links, labels, outdir, fn, Zoom(8, 40), escape, 40); +} + +String GetText(const char *s) +{ + return GetTopic(s).text; +} + +String ChangeTopicLanguage(const String &topic, int lang) { + int pos = topic.ReverseFind('$'); + if (pos < 0) + return ""; + String langtxt = ToLower(LNGAsText(lang)); + return topic.Left(pos+1) + langtxt + topic.Mid(pos+1+langtxt.GetCount()); +} + +String GetTopicLanguage(const String &topic) { + int pos = topic.ReverseFind('$'); + if (pos < 0) + return ""; + return topic.Mid(pos+1, 5); +} + +String FormatDateRFC822(const Time& t) { + int tz = int((GetSysTime()-GetUtcTime())/60); + return Format("%s, %d %Mon %d %02d:%02d:%02d %s%04d", + DayName(DayOfWeek(t)).Left(3), + t.day,t.month,t.year, + t.hour,t.minute,t.second, + tz>0?"+":"",tz/60*100+(tz+1440)%60); +} + +void CreateRssFeed() { + String header="\n" + "\n" + "Ultimate++ svn changes\n" + "http://ultimatepp.org/\n" + "This feed offers list of commits to Ultimate++ framework svn repository\n" + ""+ FormatDateRFC822(GetSysTime()) + "\n" + "en-us\n" + "\n\n"; + + String items; + for(int i = 0; i < min(30,svnlog.GetCount()); i++){ + items+="\n" + "Revision " + svnlog[i].revision + "\n" + "http://code.google.com/p/upp-mirror/source/detail?r=" + svnlog[i].revision + "\n" + "http://code.google.com/p/upp-mirror/source/detail?r=" + svnlog[i].revision + "\n" + "" + FormatDateRFC822(svnlog[i].time) + "\n" + "\n" + " Revision:" + svnlog[i].revision + "\n" + " Description:" + svnlog[i].msg + "\n" + " Submitted:" + FormatDateRFC822(svnlog[i].time) + " by " + svnlog[i].author + "\n" + " Affected files: \n" + " \n" + "

\n"; + for(int j = 0; j < svnlog[i].changes.GetCount(); j++) + items+="" + svnlog[i].changes[j].action + " " + "" + svnlog[i].changes[j].path + "
\n"; + items+= + "
\n" + " \n" + " \n" + "]]>\n" + "\n\n"; + } + SaveFile(AppendFileName(targetdir, "svnchanges.xml"), header + items + "\n\n"); +} + +VectorMap tt; + +String Www(const char *topic, int lang, String topicLocation = "topic://uppweb/www/") +{ + String strLang = ToLower(LNGAsText(lang)); + String www = GatherTopics(tt, String().Cat() << topicLocation << topic << "$" << strLang); + if (www != "index.html") + return www; + return GatherTopics(tt, String().Cat() << topicLocation << topic << "$" << "en-us"); +} + +String FolderLinks(String package, String group, int lang) +{ + String qtf; + FindFile ff(AppendFileName(AppendFileName(AppendFileName(uppsrc, package), group + ".tpp"), "*.tpp")); + while(ff) { + if(ff.IsFile()) { + if (ff.GetName().Find("en-us") >= 0) { + String title; + String tl = "topic://" + package + '/' + group + '/' + GetFileTitle(ff.GetName()); + tl = ChangeTopicLanguage(tl, lang); + GatherTopics(tt, tl, title); + qtf << "________[^" << tl << "^ " << DeQtf(Nvl(title, tl)) << "]&"; + } + } + ff.Next(); + } + return qtf; +} + +void AddFiles(String& qtf, const String& dir, const char* ext, bool& b) +{ + FindFile ff(AppendFileName(dir, "*." + String(ext))); + while(ff) { + qtf << "[A4* " << DeQtf(ff.GetName()) << "]&&" + << CppAsQtf(LoadFile(AppendFileName(dir, ff.GetName()))) + << "&&&"; + ff.Next(); + b = true; + } +} + +struct Isort { + bool operator()(const String& a, const String& b) const + { + return ToUpper(a) < ToUpper(b); + } +}; + +String MakeExamples(const char *dir, const char *www, int language) +{ + String ttxt; + FindFile ff(AppendFileName(dir, "*.*")); + ttxt << "{{1:3 "; + bool next = false; + Vector ls; + while(ff) { + if(ff.IsFolder()) + ls.Add(ff.GetName()); + ff.Next(); + } + Sort(ls, Isort()); + for(int i = 0; i < ls.GetCount(); i++) { + String name = ls[i]; + String link = String().Cat() << www << '$' << name << "$" << ToLower(LNGAsText(language)) << ".html"; + Topic& topic = tt.Add(link); + topic.title = name; + String fn = AppendFileName( + AppendFileName( + AppendFileName(uppbox, "uppweb"), + String(www) + ".tpp" + ), + topic.title + "$" + ToLower(LNGAsText(language)) + ".tpp" + ); + String h = ReadTopic(LoadFile(fn)).text; + Package p; + p.Load(AppendFileName(AppendFileName(dir, name), name + ".upp")); + topic.text << "[R6* " << name << "]&&" << DeQtf(p.description) << "&"; + if(h.GetCount()) + topic.text << h; + topic.text << "[A2 &x, String& qtf, const char *folder, int lang) +{ + if(x.Find(folder) >= 0) + return; + x.Add(folder); + String srcdoc = FolderLinks(folder, "srcdoc", lang); + String src = FolderLinks(folder, "src", lang); + Package p; + p.Load(AppendFileName(uppsrc, AppendFileName(folder, GetFileName(folder) + ".upp"))); + if(srcdoc.GetLength() || src.GetLength()) { + qtf << "&&&[*4@b " << folder << "]&"; + if(!IsNull(p.description)) + qtf << "[2 " << p.description << "]&"; + if(srcdoc.GetCount()) { + qtf << "&[3/* " + Format(t_("Using %s"), folder) << "]&"; + qtf << srcdoc; + } + if(src.GetCount()) { + qtf << "&[3/* " << Format(t_("%s reference"), folder) << "]&"; + qtf << src; + } + } +} + +int CharFilterLbl(int c) +{ + return IsAlNum(c) ? c : '.'; +} + + +void QtfAsPdf(PdfDraw &pdf, const char *qtf) +{ + RichText txt = ParseQTF(qtf); + Size page = Size(3968, 6074); + UPP::Print(pdf, txt, page); +} + +VectorMap links; +VectorMap labels; +Htmls header, lastUpdate; + +Array bar; +Array languages; + +int GetLinkLanguage(const String &link) { + int pos = link.ReverseFind('$'); + if (pos < 0) + return 0; + int lang = LNGFromText(ToUpper(link.Mid(pos+1))); + for (int i = 0; i < languages.GetCount(); ++i) { + if (languages[i] == lang) + return i; + } + return 0; +} + +void ExportPage(int i) +{ + Index css; + String path = links.GetKey(i); + RLOG("Exporting " << path); + + int ilang = GetLinkLanguage(path); + SetLanguage(languages[ilang]); + String text = GetText(path); + int h; + h = ParseQTF(tt[i].text).GetHeight(1000); + + int isvn = svndata.Find(tt.GetKey(i)); + String qtflangs; + String googleFile; + if (isvn > -1) { + String txt = String("[2 ") + t_("Last edit by %s on %s") + ".]"; + qtflangs += Format(txt, svndata[isvn].author, Format(Date(svndata[isvn].time))); + googleFile = svndata[isvn].fullPath; + if (googleFile.GetCount() > rootdir.GetCount()) + googleFile = UnixPath(googleFile.Mid(rootdir.GetCount())); + else + googleFile = ""; + } + String strlang; + Array arrLangs; + for (int il = 0; il < languages.GetCount(); ++il) { + if (il != ilang) { + String topic = ChangeTopicLanguage(path, languages[il]); + int itopic; + if ((itopic = tt.Find(topic)) >= 0) { + if (tt[itopic].title.Find(" (translated)") < 0) { + if (!strlang.IsEmpty()) + strlang << ", "; + arrLangs.Add("[^" + links[itopic] + "^ [2 " + ToLower(GetNativeLangName(languages[il])) + "]]"); + } + } + } + } + if (arrLangs.GetCount() > 0) { + for (int i = 0; i < arrLangs.GetCount(); ++i) { + if (i == arrLangs.GetCount()-1 && i != 0) + strlang << String(" ") + t_("and") + " "; + else if (i > 0) + strlang << ", "; + strlang << arrLangs[i]; + } + } + if (!strlang.IsEmpty()) + qtflangs += Format(String("[2 ") + t_("This page is also in %s") + ".]", strlang); + if (tt[i].title.Find("How to contribute. Web page") < 0) { + String help = "topic://uppweb/www/contribweb$" + ToLower(LNGAsText(languages[ilang])); + qtflangs += " " + String("[^") + help + "^ [ htmlrep; + int posB = 0; + while (true) { + posB = page.Find("[IHTMLTEXT", posB); + if (posB < 0) + break; + int posBB = posB + (int)strlen("[IHTMLTEXT"); + int pos0 = page.ReverseFind("[", posB-1); + int posE = page.Find(";2", posBB); + String html0 = page.Mid(posBB, posE - posBB); + html0.Replace("`", ""); + htmlrep.Add(html0); + int posEE = page.Find("]&]", posE) + (int)strlen("]&]"); + + page = page.Left(pos0) + "QTFHTMLTEXT" + FormatInt(htmlrep.GetCount()-1) + page.Mid(posEE+1); + } + + page = QtfAsHtml(page, css, links, labels, targetdir, links[i]); + for (int iHtml = 0; iHtml < htmlrep.GetCount(); ++iHtml) + page.Replace(String("QTFHTMLTEXT") + FormatInt(iHtml), htmlrep[iHtml]); + + Color paper = SWhite; + if(path == "topic://uppweb/www/download$en-us") + page << LoadFile(GetRcFile("adsense3.txt")); +/* if(path == "topic://uppweb/www/index$en-us") { + for(int q = 0; q < news.GetCount(); q++) { + String n = GetText("uppweb/www_news/" + news[q]); + String h = news[q]; + int i = h.Find('$'); + if(i >= 0) + h = h.Mid(0, i); + if(h.GetLength() == 8) + h = h.Mid(0, 4) + '-' + h.Mid(4, 2) + '-' + h.Mid(6, 2); + page << "
"; + page << "
  " + << h << "

"; + page << QtfAsHtml(n, css, links, targetdir, FormatIntAlpha(q) + "_n"); + page << "
"; + } + }*/ + Color bg = Color(210, 217, 210); + Htmls footer; + footer << HtmlTable().Border(0).Width(-100) / HtmlLine() + + RoundFrame(HtmlPadding(8) / langs , "6E89AE;padding: 10px;", White); + Htmls html; + html << + HtmlPackedTable().Width(-100) / + HtmlLine().ColSpan(3) / header + + HtmlPackedTable().Width(-100) / ( + HtmlLine().ColSpan(3).BgColor(bg).Height(6) / "" + + HtmlRow() / ( + HtmlTCell().Center() / BoxWidth(160).Center() / ( + bar[GetLinkLanguage(path)] + + "
" + + LoadFile(GetRcFile("facebook.txt")) + + "

" + +// "

" + + LoadFile(GetRcFile("adsense2.txt")) + + "

" + + LoadFile(GetRcFile("adlinks.txt")) + + (h > 25000 ? "

" + LoadFile(GetRcFile("adsense2.txt")) + : "") + + "


" + +// LoadFile(GetRcFile("referral.txt")) + +// LoadFile(GetRcFile("referral2.txt")) + +// LoadFile(GetRcFile("donations.txt")) + +// "

" + +// amazon[i % amazon.GetCount()] + + "


" + + HtmlLink("http://sourceforge.net/projects/upp/") / + HtmlImg("http://sourceforge.net/sflogo.php?group_id=93970&type=2", + "SourceForge.net Logo").Border(0).Width(125).Height(37) + + "

" + + HtmlLink("http://www.sdjournal.org/en/") / + HtmlImg(GetImageSrc(WWW::Sdj)).Border(0) + + "

" + + (links[i] == "index.html" ? lastUpdate : Htmls()) + + HtmlImg("http://www.vol.cz/cgi-bin/wc/upp").Width(1).Height(1) + ) + + HtmlTCell().BgColor(bg) / BoxWidth(6) / "" + + HtmlTCell().Width(-100).BgColor(bg) / ( + RoundFrame(HtmlPadding(8) / page , "6E89AE;padding: 10px;", White) + + footer + ) + ) + ); + + String topicTitle = tt.GetKey(i); + String pageTitle = tt[i].title; + if(IsNull(pageTitle)) + pageTitle = "Ultimate++"; + if(StartsWith(topicTitle, "examples$")) + pageTitle = "Demos / " + pageTitle; + else if(StartsWith(topicTitle, "reference$")) + pageTitle = "Examples / " + pageTitle; + + if(pageTitle != "Ultimate++") + pageTitle << " :: Ultimate++"; + + Htmls content = + "\n" + + HtmlHeader(pageTitle, AsCss(css) + + "a.l1 { text-decoration:none; font-size: 8pt; font-family: sans-serif; " + "font-weight: normal; }\n" + "a.l1:link { color:#000000; }\n" + "a.l1:visited { color:#000080; }\n" + "a.l1:hover { color:#9933CC; }\n" + "a.l1:active { color:#000000; }\n" + "a.l2 { text-decoration:none; font-size: 12pt; font-family: sans-serif; " + "font-variant: small-caps; }\n" + "a.l2:link { color:#0066FF; }\n" + "a.l2:visited { color:#FF6600; }\n" + "a.l2:hover { color:#BC0624; }\n" + "a.l2:active { color:#BC0024; }\n", + "" + "\n" + "" +// "" + ) + + + .BgColor(bg) + .Alink(Red).Link(Black).Vlink(Blue) + / html; + SaveFile(AppendFileName(targetdir, links[i]), content); + RLOG("Exported page " << links[i]); +} + + +struct ProgramData { + String rootdir; + String targetdir; + String diffdir; + String pdfdir; + bool ftpUpload; + bool outPdf; + bool doSvn; + void Xmlize(XmlIO xml) { + xml + ("rootdir", rootdir) + ("targetdir", targetdir) + ("diffdir", diffdir) + ("pdfdir", pdfdir) + ("ftpUpload", ftpUpload) + ("outPdf", outPdf) + ("doSvn", doSvn) + ; + } +}; + +CONSOLE_APP_MAIN +{ +#ifdef PLATFORM_POSIX + StdLogSetup(LOG_COUT); + rootdir = GetHomeDirFile("upp.src"); + targetdir = GetHomeDirFile("uppwww"); + diffdir = GetHomeDirFile("wwwupp"); + pdfdir = GetHomeDirFile("pdf"); +#endif + outPdf = true; + doSvn = true; + + RLOG("--- uppweb started at " << GetSysTime()); + + ProgramData data; + + String configFile = GetHomeDirFile("uppweb.xml"); + bool cfgloaded = false; + if (FileExists(configFile)) { + if (LoadFromXMLFile(data, configFile)) { + rootdir = data.rootdir; + targetdir = data.targetdir; + diffdir = data.diffdir; + pdfdir = data.pdfdir; +// ftpupload = data.ftpUpload; + outPdf = data.outPdf; + doSvn = data.doSvn; + cfgloaded = true; + } + } + if (!cfgloaded) { + data.rootdir = rootdir; + data.targetdir = targetdir; + data.diffdir = diffdir; + data.pdfdir = pdfdir; +// data.ftpUpload = ftpupload; + data.outPdf = outPdf; + data.doSvn = doSvn; + StoreAsXMLFile(data, NULL, configFile); + } + Cout() << "RootDir: " << rootdir << "\n"; + Cout() << "TargetDir: " << targetdir << "\n"; + + if (!DirectoryExists(rootdir)) { + Cout() << ("Directory " + DeQtf(rootdir) + " does not exist\n"); + return; + } + + uppbox = AppendFileName(rootdir, "uppbox"); + uppsrc = AppendFileName(rootdir, "uppsrc"); + reference = AppendFileName(rootdir, "reference"); + examples = AppendFileName(rootdir, "examples"); + bazaar = AppendFileName(rootdir, "bazaar"); + + Cout() << "Loading www.tpp\n"; + InitWwwTpp(); + + languages.Add(LNG_('E','N','U','S')); // en-us has to be the first one + languages.Add(LNG_('C','A','E','S')); + languages.Add(LNG_('C','S','C','Z')); + languages.Add(LNG_('D','E','D','E')); + languages.Add(LNG_('E','S','E','S')); + languages.Add(LNG_('F','R','F','R')); + languages.Add(LNG_('R','O','R','O')); + languages.Add(LNG_('R','U','R','U')); + languages.Add(LNG_('Z','H','C','N')); + languages.Add(LNG_('Z','H','T','W')); + + RealizeDirectory(targetdir); + + if (outPdf) { + RealizeDirectory(pdfdir); + } + Cout() << "Gather ref links " << uppsrc << "\n"; + GatherRefLinks(uppsrc); + Cout() << "Gather ref links " << AppendFileName(rootdir, "bazaar") << "\n"; + GatherRefLinks(AppendFileName(rootdir, "bazaar")); + + SaveFile(AppendFileName(targetdir, "sdj.gif"), LoadFile(GetRcFile("sdj.gif"))); + + String release = "4193"; + escape.Add("RELEASE", release); + escape.Add("RELEASET", release); + escape.Add("UPDATETIME", Format("%`", GetUtcTime())); + + if (doSvn) { + Cout() << "Processing svn\n"; + GetSvnList(svndata, rootdir); + GetSvnLog(svnlog); + CreateRssFeed(); + if (svnlog.GetCount() > 0) { + escape.Add("LATESTSVN", svnlog[0].revision); + //Index css; + //escape.Add("SVNTABLE", QtfAsHtml(SvnChanges(svnlog, "", 100), css, links, labels, targetdir)); + //escape.Add("ANCHOR", ""); + } + } + + escape.Add("PAYPAL", LoadFile(GetRcFile("donations.txt"))); + + header = HtmlPackedTable() + .Width(-100) + .BgColor(White) + .Attr("style", "border: 1px solid #6E89AE;" + "padding-left: 10px;padding-right: 0px;padding-top: 0px;padding-bottom: 0px;") + / + HtmlRow() / ( + HtmlCell() / HtmlLink("index.html") / Wimg(WWW::Logo6) + + HtmlCell().Right().Bottom() + .Style("padding-bottom: 5px; " + "background-image: url('" + GetImageSrc(WWW::HB) + "')") + / HtmlArial(14) / (LoadFile(GetRcFile("adsense.txt")) + "  "/* + "
..harnessing the real power of C++  "*/) + ); + + bar.SetCount(languages.GetCount()); + + int lang = GetCurrentLanguage(); + for (int i = 0; i < languages.GetCount(); ++i) { + Cout() << "Language " << LNGAsText(languages[i]); + Htmls bi, bex, bdoc, bcom, bcon, bsearch, blang; + + SetLanguage(languages[i]); + + Www("index", languages[i]); + Www("contribweb", languages[i]); + // bi << BarLink("index.html", "Home", false); + bi << BarLink(Www("overview", languages[i]), t_("Overview"), false); + bi << BarLink(Www("examples", languages[i]), t_("Examples")); + { + int di = tt.Find("topic://uppweb/www/examples$" + ToLower(LNGAsText(languages[i]))); + tt[di].text << MakeExamples(examples, "examples", languages[i]); + tt[di].text << GetTopic("topic://uppweb/www/reference$" + ToLower(LNGAsText(languages[i]))).text; + tt[di].text << MakeExamples(reference, "reference", languages[i]); + } + + bi << BarLink(Www("ss", languages[i]), t_("Screenshots")); + bi << BarLink(Www("comparison", languages[i]), t_("Comparisons")); + bi << BarLink(Www("apps", languages[i]), t_("Applications")); + bi << BarLink(Www("download", languages[i]), t_("Download")); + + bi << BarLink(Www("documentation", languages[i]), t_("Manual")); + { + int di = tt.Find("topic://uppweb/www/documentation$" + ToLower(LNGAsText(languages[i]))); + if (di >= 0) { + Index x; + x.Clear(); + String qtf; + SrcDocs(x, qtf, "Core", languages[i]); + SrcDocs(x, qtf, "Draw", languages[i]); + SrcDocs(x, qtf, "CtrlCore", languages[i]); + SrcDocs(x, qtf, "CtrlLib", languages[i]); + SrcDocs(x, qtf, "RichText", languages[i]); + SrcDocs(x, qtf, "RichEdit", languages[i]); + FindFile ff(AppendFileName(uppsrc, "*.*")); + Array folders; + folders.Clear(); + while(ff) { + if(ff.IsFolder()) + folders.Add(ff.GetName()); + ff.Next(); + } + Sort(folders); + for (int ifold = 0; ifold < folders.GetCount(); ++ifold) + SrcDocs(x, qtf, folders[ifold], languages[i]); + tt[di].text << qtf; + } + } + bi << BarLink(Www("bazaar", languages[i]), t_("Bazaar")); + bi << BarLink(Www("Roadmap", languages[i]), t_("Status & Roadmap")); + bi << BarLink(Www("FAQ", languages[i]), t_("FAQ")); + bi << BarLink(Www("About", languages[i], "topic://ide/app/"), t_("Authors & License")); + + bi << BarLink("http://www.ultimatepp.org/forum", t_("Forums")); + // bcom << BarLink(Www("mailing"), "Mailing lists"); + // bi << BarLink("http://www.ultimatepp.org/wiki/index.php", "Wiki"); + bi << BarLink(Www("Funding", languages[i]), t_("Funding Ultimate++")); + // bcom << BarLink(Www("helpus"), "Getting involved"); + // bcom << BarLink("mailto: upp@ntllib.org", "Contact developers"); + + bsearch << BarCaption(t_("Search on this site")); + bsearch << SearchBar("www.ultimatepp.org"); + + //blang << BarCaptionLang(t_("Languages")); + //blang << BarLink(Www("English", languages[i]), t_("Bazaar")); + //blang << BarLink(Www("Russian", languages[i]), t_("Bazaar")); + + HtmlTag bf = HtmlPackedTable() + .Width(-100) + .BgColor(White) + .Attr("style", "border-style: solid; border-width: 1px; border-color: #6E89AE;" + "padding: 0px"); + String div = HtmlTable().Border(0).Width(-100) / HtmlLine(); + bar[i] = bf / bi + div + + // bf / bex + div + + // bf / bdoc + div + + // bf / bcom + div + + // bf / bcon + div + + bf / bsearch + div; + //bf / blang; + } + SetLanguage(lang); + + for(int i = 0; i < tt.GetCount(); i++) { + String topic = tt.GetKey(i); + links.Add(topic, topic == "topic://uppweb/www/index$en-us" ? "index.html" : + memcmp(topic, "topic://", 8) ? topic : TopicFileNameHtml(topic)); + } + + String svntableStr = DeQtf("[svntable]"); + for(int i = 0; i < tt.GetCount(); i++) { + if (tt[i].title == "Svn releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 300, "")); + else if (tt[i].title == "Svn Web releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppweb")); + else if (tt[i].title == "Svn Bazaar releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "bazaar")); + else if (tt[i].title == "Svn Upp releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppsrc")); + else if (tt[i].title == "Svn major releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 300, "", true)); + else if (tt[i].title == "Svn Web major releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppweb", true)); + else if (tt[i].title == "Svn Bazaar major releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "bazaar", true)); + else if (tt[i].title == "Svn Upp major releases") + tt[i].text.Replace(svntableStr, SvnChanges(svnlog, 100, "uppsrc", true)); + else if (links[i].Find("index") >= 0) { + String win32 = "upp-win32-RELEASE.exe"; + String win32release = win32; + win32release.Replace(String("RELEASE"), release); + String x11 = "upp-x11-src-RELEASE.tar.gz"; + String x11release = x11; + x11release.Replace(String("RELEASE"), release); + tt[i].text.Replace(DeQtf(x11), DeQtf(x11release)); + tt[i].text.Replace(DeQtf(win32), DeQtf(win32release)); + } + } + + for(int i = 0; i < reflink.GetCount(); i++) { + String l = reflink.GetKey(i); + String lbl = Filter(l, CharFilterLbl); + String f = links.Get(reflink[i], Null) + '#' + lbl; + links.Add(l, f); + static const char *x[] = { "::struct", "::class", "::union" }; + for(int ii = 0; ii < 3; ii++) { + String e = x[ii]; + if(EndsWith(l, e)) { + links.Add(l.Mid(0, l.GetLength() - e.GetLength()), f); + } + } + labels.Add(l, lbl); + } + + Date d = GetSysDate(); + lastUpdate = HtmlItalic() / HtmlArial(8) / HtmlFontColor(Gray()) / + (String().Cat() << "Last update " << GetSysDate()); + +// Vector amazon = Split(LoadFile(GetRcFile("amazon.txt")), '\n');//440 + + Vector bazaarItems = SvnBazaarList(bazaar, svnlog); + + // To fill Bazaar page with real release dates and size + for(int i = 0; i < tt.GetCount(); i++) { + if (tt[i].title == "Bazaar") { + String page = tt[i]; + for (int j = 0; j < bazaarItems.GetCount(); ++j) { + int pos = page.Find("2 " + DeQtf(bazaarItems[j].name) + "]]"); + if (pos < 0) + pos = page.Find("2 " + DeQtf(bazaarItems[j].name) + "\r\n]]"); + if (pos >= 0) { + pos = page.Find("::", pos); + pos = page.Find("::", pos); + pos = page.Find(":: [s0;=2", pos); + if (pos >= 0) + pos += (int)strlen(":: [s0;=2"); + String strDate; + if (pos >= 0) { + Time t = bazaarItems[j].lastChange; + if (IsNull(t)) + strDate = "Not in Svn log"; + else + strDate = Format("%Mon", t.month) + " " + FormatInt(t.year); + page.Insert(pos, " " + strDate); + } + pos = page.Find(":: [s0;=2", pos); + if (pos >= 0) + pos += (int)strlen(":: [s0;=2"); + String strSz; + if (pos >= 0) { + if (bazaarItems[j].size == 0) + strSz = "Not in Svn log"; + else + strSz = BytesToString(bazaarItems[j].size); + + page.Insert(pos, " " + strSz); + } + } + } + tt[i].text = page; + } + } + + LLOG("G: " << MemoryUsedKb()); + +/* + if (outPdf) { + PdfDraw pdf; + for(int i = 0; i < tt.GetCount(); i++) + QtfAsPdf(pdf, tt[i]); + SaveFile(AppendFileName(pdfdir, "Upp.pdf"), pdf.Finish()); + } +*/ + + LLOG("H: " << MemoryUsedKb()); + + for(int i = 0; i < tt.GetCount(); i++) + ExportPage(i); + SetLanguage(lang); + + LLOG("I: " << MemoryUsedKb()); + +// SaveFile(AppendFileName(targetdir, "favicon.ico"), LoadFile(AppendFileName(uppsrc, "ide/ide.ico"))); + SaveFile(AppendFileName(targetdir, "stats.html"), + HtmlImg("http://www.vol.cz/cgi-bin/wc/upp") + "
" + + HtmlLink("http://www.mygooglepagerank.com", "_blank") / + "" + + "" + + HtmlLink("http://www.mygooglepagerank.com", "_blank") / + "" + + "" + ); + Cout() << "Finished OK\n"; + +#if 0 // we are now doing this on server, directly copying to www directory + + if (!ftpupload) + return; + + RLOG("uppweb Finished, now about to upload the content"); + + Vector upload; + { + FindFile ff(AppendFileName(targetdir, "*.*")); + while(ff) { + if(ff.IsFile()) { + String s = LoadFile(AppendFileName(targetdir, ff.GetName())); + String f = AppendFileName(diffdir, ff.GetName()); + if(LoadFile(f) != s) { + upload.Add(ff.GetName()); + RLOG("upload: " << ff.GetName()); + } + } + ff.Next(); + } + } + RealizeDirectory(diffdir); + + if(upload.GetCount()) { + FtpClient ftp; + RLOG("Connecting ftp..."); + if(!ftp.Connect(getenv("UPPFTP"), getenv("UPPFTPUSR"), getenv("UPPFTPPWD"), true)) { + RLOG("Unable to connect!" + ftp.GetError()); + SetExitCode(1); + return; + } + if(!ftp.Cd("www")) { + RLOG("Unable to 'cd www'"); + SetExitCode(1); + return; + } + for(int i = 0; i < upload.GetCount(); i++) { + RLOG("Uploading " << upload[i]); + String s = LoadFile(AppendFileName(targetdir, upload[i])); + if(!ftp.Save(upload[i], s)) { + RLOG("FTP error (file upload): " + ftp.GetError()); + SetExitCode(1); + return; + } + SaveFile(AppendFileName(diffdir, upload[i]), s); + } + } + BeepInformation(); +#endif +} diff --git a/uppbox/uppweb/www.h b/uppbox/uppweb/www.h index a9ee4d10a..bd376c8d8 100644 --- a/uppbox/uppweb/www.h +++ b/uppbox/uppweb/www.h @@ -1,75 +1,77 @@ -#ifndef _uppweb_www_h_ -#define _uppweb_www_h_ - -// upp web forum counter at 11/11 453604 - -#include -#include -#include -#include -#include - -using namespace Upp; - -#ifdef _MULTITHREADED -#define MTC -#endif - -struct SvnListRev : Moveable { - String author; - int revision; - Time time; - String fullPath; -}; - -struct SvnLogRev : Moveable { - String revision; - String author; - Time time; - struct SvnChange : Moveable { - String kind; - String action; - String path; - }; - Vector changes; - String msg; - Index tags; - bool major; -}; - -struct SvnBazaarItems : Moveable { - String name; - int64 size; - Time lastChange; - String description; - String authors; - String status; - String externalDependencies; - String supportedOS; - String imagePath; -}; - -extern String uppsrc; -extern String uppbox; -extern String bazaar; -extern String rootdir; -extern VectorMap reflink; -extern VectorMap svndata; -extern Vector svnlog; - -String TopicFileName(const char *dir, const char *topic); -String TopicFileNameHtml(const char *topic); -String GatherTopics(VectorMap& map, const char *topic, String& title); -String GatherTopics(VectorMap& map, const char *topic); - -String CppAsQtf(const String& s); - -void GatherRefLinks(const char *upp); - -void GetSvnList(VectorMap &data, const String &); -void GetSvnLog(Vector &log, int limit = -1); -String SvnChanges(Vector &log, int limit, String filter, bool major = false); -Vector SvnBazaarList(String bazaarPath, Vector &log); -String BytesToString(uint64 _bytes, bool units = true); - -#endif +#ifndef _uppweb_www_h_ +#define _uppweb_www_h_ + +// upp web forum counter at 11/11 453604 + +#include +#include +#include +#include +#include + +using namespace Upp; + +#ifdef _MULTITHREADED +#define MTC +#endif + +void InitWwwTpp(); + +struct SvnListRev : Moveable { + String author; + int revision; + Time time; + String fullPath; +}; + +struct SvnLogRev : Moveable { + String revision; + String author; + Time time; + struct SvnChange : Moveable { + String kind; + String action; + String path; + }; + Vector changes; + String msg; + Index tags; + bool major; +}; + +struct SvnBazaarItems : Moveable { + String name; + int64 size; + Time lastChange; + String description; + String authors; + String status; + String externalDependencies; + String supportedOS; + String imagePath; +}; + +extern String uppsrc; +extern String uppbox; +extern String bazaar; +extern String rootdir; +extern VectorMap reflink; +extern VectorMap svndata; +extern Vector svnlog; + +String TopicFileName(const char *dir, const char *topic); +String TopicFileNameHtml(const char *topic); +String GatherTopics(VectorMap& map, const char *topic, String& title); +String GatherTopics(VectorMap& map, const char *topic); + +String CppAsQtf(const String& s); + +void GatherRefLinks(const char *upp); + +void GetSvnList(VectorMap &data, const String &); +void GetSvnLog(Vector &log, int limit = -1); +String SvnChanges(Vector &log, int limit, String filter, bool major = false); +Vector SvnBazaarList(String bazaarPath, Vector &log); +String BytesToString(uint64 _bytes, bool units = true); + +#endif