ultimatepp/bazaar/Functions4U/GatherTpp.cpp
koldo a5dbfab40a *Functions4U: Fixed problem in Dl
git-svn-id: svn://ultimatepp.org/upp/trunk@15759 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2021-02-12 17:38:00 +00:00

432 lines
No EOL
12 KiB
C++

#ifdef flagGUI
#include <CtrlLib/CtrlLib.h>
#include <PdfDraw/PdfDraw.h>
//#include <ide/Browser/Browser.h>
#include <Functions4U/Functions4U.h>
#include "GatherTpp.h"
#include <Functions4U/Html/htmld.h>
namespace Upp {
static Topic ReadTopic(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 = ZDecompress(~b, b.GetLength());
} else {
topic.text << p.GetPtr();
break;
}
}
}
catch(CParser::Error &e) {
topic.text = String::GetVoid();
topic.title = e;
}
return topic;
}
struct ScanTopicIterator : RichText::Iterator {
VectorMap<String, String> *reflink;
String link;
StaticCriticalSection reflink_lock;
ScanTopicIterator(VectorMap<String, String> *_reflink) : reflink(_reflink) {};
virtual bool operator()(int , const RichPara& para)
{
if(!IsNull(para.format.label))
reflink->Add(para.format.label, link);
return false;
}
};
void GatherTpp::GatherRefLinks(const char *upp)
{
for(FindFile pff(AppendFileName(upp, "*.*")); pff; pff.Next()) {
if(pff.IsFolder()) {
String package = pff.GetName();
String pdir = AppendFileName(upp, package);
TopicLink tl;
tl.package = package;
for(FindFile ff(AppendFileName(pdir, "*.tpp")); ff; ff.Next()) {
if(ff.IsFolder()) {
String group = GetFileTitle(ff.GetName() );
tl.group = group;
String _dir = AppendFileName(pdir, ff.GetName());
for(FindFile ft(AppendFileName(dir, "*.tpp")); ft; ft.Next()) {
if(ft.IsFile()) {
String path = AppendFileName(_dir, ft.GetName());
tl.topic = GetFileTitle(ft.GetName());
String link = TopicLinkString(tl);
ScanTopicIterator sti(&reflink);
sti.link = link;
ParseQTF(ReadTopic(LoadFile(path))).Iterate(sti);
}
}
}
}
}
}
}
struct GatherLinkIterator : RichText::Iterator {
VectorMap<String, String> *reflink;
Index<String> link;
explicit GatherLinkIterator(VectorMap<String, String> *_reflink) : reflink(_reflink) {};
virtual bool operator()(int , const RichPara& para)
{
for(int i = 0; i < para.GetCount(); i++) {
String l = para[i].format.link;
if(!IsNull(l)) {
if(l[0] == ':') {
int q = reflink->Find(l);
if(q < 0)
q = reflink->Find(l + "::class");
if(q < 0)
q = reflink->Find(l + "::struct");
if(q < 0)
q = reflink->Find(l + "::union");
if(q >= 0)
l = (*reflink)[q];
}
link.FindAdd(Nvl(reflink->Get(l, Null), l));
}
}
return false;
}
};
String GetIndexTopic(String file)
{
String topic = GetFileTitle(file);
String folder = GetFileFolder(file);
String topicLocation = GetFileTitle(folder);
folder = GetUpperFolder(folder);
topicLocation = GetFileTitle(folder) + "/" + topicLocation;
return "topic://" + topicLocation + "/" + topic;
}
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);
}
HtmlsD RoundFrame(HtmlsD data, String border, Color bg)
{
return HtmlPackedTableD()
.BgColor(bg).Width(-100)
.Attr("style", "border-style: solid; border-width: 1px; border-color: #" + border + ";")
/ HtmlLineD() / data;
}
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 GatherTpp::QtfAsHtml(const char *qtf, Index<String>& css,
const VectorMap<String, String>& _links,
const VectorMap<String, String>& _labels,
const String& outdir, const String& fn)
{
return EncodeHtml(ParseQTF(qtf), css, _links, _labels, outdir, fn, Zoom(8, 40), escape, 40);
}
String GetText(const char *s)
{
return GetTopic(s).text;
}
void GatherTpp::ExportPage(int i, String htmlFolder, String _keywords)
{
Index<String> css;
String path = links.GetKey(i);
String qtflangs;
String strlang;
String page = tt[i];
page = QtfAsHtml(page, css, links, labels, htmlFolder, links[i]);
Color bg = Color(210, 217, 210);
HtmlsD html;
html <<
HtmlPackedTableD().Width(-100) /
HtmlLineD().ColSpan(3) +
HtmlPackedTableD().Width(-100) / (
HtmlLineD().ColSpan(3).BgColor(bg).Height(6) / "" +
HtmlRowD() / (
HtmlTCellD().Width(-100).BgColor(bg) / (
RoundFrame(page , "6E89AE;padding: 10px;", White)
)
)
);
//String topicTitle = tt.GetKey(i);
String pageTitle = tt[i].title;
if(IsNull(pageTitle))
pageTitle = title;
/*
if(StartsWith(topicTitle, "examples$"))
pageTitle = "Demos / " + pageTitle;
else if(StartsWith(topicTitle, "reference$"))
pageTitle = "Examples / " + pageTitle;
*/
if(pageTitle != title)
pageTitle << " :: " << title;
HtmlsD content =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" +
HtmlHeaderD(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",
"<META NAME=\"keywords\" "
"CONTENT=\"" + _keywords + "\">"
"<META name=\"robots\" content=\"index,follow\">"
)
.BgColor(bg)
.Alink(Red).Link(Black).Vlink(Blue)
/ html;
SaveFile(AppendFileName(htmlFolder, links[i]), ~content);
}
String GatherTpp::TopicFileName(const char *topic)
{
TopicLink tl = ParseTopicLink(topic);
String file = AppendFileName(dir, AppendFileName(tl.group + ".tpp", tl.topic + ".tpp"));
if (FileExists(file))
return file;
for (int i = 0; i < rootFolders.GetCount(); ++i) {
if (rootFolders[i] != dir) {
file = AppendFileName(rootFolders[i], AppendFileName(tl.package , AppendFileName(tl.group + ".tpp", tl.topic + ".tpp")));
if (FileExists(file))
return file;
}
}
return "";
}
String TopicFileNameHtml(const char *topic)
{
TopicLink tl = ParseTopicLink(topic);
return tl.group + "$" + tl.package+ "$" + tl.topic + ".html";
}
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 GatherTpp::GatherTopics(const char *topic, String& _title)
{
static StaticCriticalSection mapl;
int q;
INTERLOCKED_(mapl)
q = tt.Find(topic);
if(q < 0) {
Topic p = ReadTopic(LoadFile(TopicFileName(topic)));
_title = p.title;
String t = p;
if(IsNull(t)) {
String topicEng = ChangeTopicLanguage(topic, LNG_('E','N','U','S'));
p = ReadTopic(LoadFile(TopicFileName(topicEng)));
String _tt = p;
if(IsNull(_tt))
return "index.html";
_title = p.title;
p.title += " (translated)";
String help = "topic://uppweb/www/contribweb$" + GetTopicLanguage(topic);
p.text = String("{{1f1t0/50b0/50@(240.240.240) [<A2 ") + t_("This page has not been translated yet") +
"]. " + "[^" + help + "^ [<A2 " + t_("Do you want to translate it?") + "]]}}&&" + p.text;
}
INTERLOCKED_(mapl)
tt.Add(topic) = p;
GatherLinkIterator ti(&reflink);
ParseQTF(t).Iterate(ti);
#ifdef MTC
CoWork work;
for(int i = 0; i < ti.link.GetCount(); i++)
work & callback2(sGatherTopics, &tt, ti.link[i]);
#else
for(int i = 0; i < ti.link.GetCount(); i++)
GatherTopics(ti.link[i]);
#endif
} else {
INTERLOCKED_(mapl)
_title = tt[q].title;
}
return TopicFileNameHtml(topic);
}
String GatherTpp::GatherTopics(const char *topic)
{
String dummy;
return GatherTopics(topic, dummy);
}
bool GatherTpp::Load(String indexFile, Gate2<int, int> progress) {
indexTopic = GetIndexTopic(indexFile);
for (int i = 0; i < rootFolders.GetCount(); ++i) {
if (progress(i+1, rootFolders.GetCount()))
return false;
dir = rootFolders[i];
if (!DirectoryExists(dir))
return false;
GatherRefLinks(dir);
if (i == 0)
GatherTopics(indexTopic);
}
return true;
}
bool GatherTpp::MakeHtml(const char *folder, Gate2<int, int> progress) {
DeleteFolderDeep(folder); Sleep(100);
DirectoryCreate(folder);
for(int i = 0; i < tt.GetCount(); i++) {
String topic = tt.GetKey(i);
links.Add(topic, topic == indexTopic ? "index.html" :
memcmp(topic, "topic://", 8) ? topic : TopicFileNameHtml(topic));
}
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);
}
for(int i = 0; i < tt.GetCount(); i++) {
if (progress(i+1, tt.GetCount()))
return false;
ExportPage(i, folder);
}
return true;
}
bool GatherTpp::MakePdf(const char *filename, Gate2<int, int> progress) {
PdfDraw pdf;
for(int i = 0; i < tt.GetCount(); i++) {
if (progress(int(0.6*(i+1)), tt.GetCount()))
return false;
bool dopdf = true;
for (int j = 0; j < i; ++j) {
if (tt[j].text == tt[i].text) {
dopdf = false;
break;
}
}
if (dopdf)
QtfAsPdf(pdf, tt[i]);
}
String rawPdf = pdf.Finish(); progress(9, 10);
SaveFile(filename, rawPdf); progress(10, 10);
return true;
}
int GatherTpp::FindTopic(const String name) {
return tt.Find(name);
}
Topic &GatherTpp::GetTopic(int id) {
return tt[id];
}
Topic &GatherTpp::AddTopic(const String name) {
return tt.Add(name);
}
String GatherTpp::Www(const char *topic, int lang, String topicLocation) {
String strLang = ToLower(LNGAsText(lang));
String www = GatherTopics(String().Cat() << topicLocation << topic << "$" << strLang);
if (www != "index.html")
return www;
return GatherTopics(String().Cat() << topicLocation << topic << "$" << "en-us");
}
}
#endif