From 7b887cfbffd73ea12fe0171c149f49c4540aac40 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 27 Sep 2015 17:40:38 +0200 Subject: Added support for encoding tag to the template engine used for HTML help indices --- src/template.cpp | 187 +++++++++++++++++++++++++++++++++--- templates/html/htmlhelpindexhhp.tpl | 33 +++++++ templates/html/htmllayout.tpl | 7 ++ 3 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 templates/html/htmlhelpindexhhp.tpl diff --git a/src/template.cpp b/src/template.cpp index 69eb440..3e354c3 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -34,6 +34,7 @@ #include "message.h" #include "util.h" #include "resourcemgr.h" +#include "portable.h" #define ENABLE_TRACING 0 @@ -552,6 +553,10 @@ class TemplateContextImpl : public TemplateContext if (m_activeEscapeIntf) m_activeEscapeIntf->enableTabbing(b); } bool tabbingEnabled() const { return m_tabbingEnabled; } + bool needsRecoding() const { return !m_encoding.isEmpty(); } + QCString encoding() const { return m_encoding; } + void setEncoding(const QCString &file,int line,const QCString &enc); + QCString recode(const QCString &s); void warn(const char *fileName,int line,const char *fmt,...) const; // index related functions @@ -573,6 +578,8 @@ class TemplateContextImpl : public TemplateContext bool m_tabbingEnabled; TemplateAutoRef m_indices; QDict< QStack > m_indexStacks; + QCString m_encoding; + void *m_fromUtf8; }; //----------------------------------------------------------------------------- @@ -2303,6 +2310,7 @@ TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e) m_indexStacks.setAutoDelete(TRUE); m_contextStack.setAutoDelete(TRUE); m_escapeIntfDict.setAutoDelete(TRUE); + m_fromUtf8 = (void*)(-1); push(); set("index",m_indices.get()); } @@ -2312,6 +2320,49 @@ TemplateContextImpl::~TemplateContextImpl() pop(); } +void TemplateContextImpl::setEncoding(const QCString &templateName,int line,const QCString &enc) +{ + if (enc==m_encoding) return; // nothing changed + if (m_fromUtf8!=(void *)(-1)) + { + portable_iconv_close(m_fromUtf8); + m_fromUtf8 = (void*)(-1); + } + m_encoding=enc; + if (!enc.isEmpty()) + { + m_fromUtf8 = portable_iconv_open(enc,"UTF-8"); + if (m_fromUtf8==(void*)(-1)) + { + warn(templateName,line,"unsupported character conversion: '%s'->'UTF-8'\n", enc.data()); + } + } + //printf("TemplateContextImpl::setEncoding(%s)\n",enc.data()); +} + +QCString TemplateContextImpl::recode(const QCString &s) +{ + //printf("TemplateContextImpl::recode(%s)\n",s.data()); + int iSize = s.length(); + int oSize = iSize*4+1; + QCString output(oSize); + size_t iLeft = iSize; + size_t oLeft = oSize; + char *iPtr = s.rawData(); + char *oPtr = output.rawData(); + if (!portable_iconv(m_fromUtf8,&iPtr,&iLeft,&oPtr,&oLeft)) + { + oSize -= (int)oLeft; + output.resize(oSize+1); + output.at(oSize)='\0'; + return output; + } + else + { + return s; + } +} + void TemplateContextImpl::set(const char *name,const TemplateVariant &v) { TemplateVariant *pv = m_contextStack.getFirst()->find(name); @@ -2586,16 +2637,30 @@ class TemplateNodeText : public TemplateNode void render(FTextStream &ts, TemplateContext *c) { - //printf("TemplateNodeText::render(%s)\n",m_data.data()); TemplateContextImpl* ci = dynamic_cast(c); if (ci==0) return; // should not happen + //printf("TemplateNodeText::render(%s) needsRecoding=%d ci=%p\n",m_data.data(),ci->needsRecoding(),ci); if (ci->spacelessEnabled()) { - ts << ci->spacelessIntf()->remove(m_data); + if (ci->needsRecoding()) + { + ts << ci->recode(ci->spacelessIntf()->remove(m_data)); + } + else + { + ts << ci->spacelessIntf()->remove(m_data); + } } else { - ts << m_data; + if (ci->needsRecoding()) + { + ts << ci->recode(m_data); + } + else + { + ts << m_data; + } } } private: @@ -2638,11 +2703,25 @@ class TemplateNodeVariable : public TemplateNode } if (ci->escapeIntf() && !v.raw()) { - ts << ci->escapeIntf()->escape(v.toString()); + if (ci->needsRecoding()) + { + ts << ci->recode(ci->escapeIntf()->escape(v.toString())); + } + else + { + ts << ci->escapeIntf()->escape(v.toString()); + } } else { - ts << v.toString(); + if (ci->needsRecoding()) + { + ts << ci->recode(v.toString()); + } + else + { + ts << v.toString(); + } } } } @@ -2791,7 +2870,7 @@ class TemplateNodeIf : public TemplateNodeCreator if (guardValue.toBool()) // render nodes for the first guard that evaluated to 'true' { nodes->trueNodes.render(ts,c); - processed=TRUE; + processed=TRUE; } } else @@ -3961,11 +4040,25 @@ class TemplateNodeCycle : public TemplateNodeCreator } if (ci->escapeIntf() && !v.raw()) { - ts << ci->escapeIntf()->escape(v.toString()); + if (ci->needsRecoding()) + { + ts << ci->recode(ci->escapeIntf()->escape(v.toString())); + } + else + { + ts << ci->escapeIntf()->escape(v.toString()); + } } else { - ts << v.toString(); + if (ci->needsRecoding()) + { + ts << ci->recode(v.toString()); + } + else + { + ts << v.toString(); + } } } if (++m_index==m_args.count()) // wrap around @@ -4109,7 +4202,14 @@ class TemplateNodeMarkers : public TemplateNodeCreator int index=0,newIndex,matchLen; while ((newIndex=marker.match(str,index,&matchLen))!=-1) { - ts << str.mid(index,newIndex-index); // write text before marker + if (ci->needsRecoding()) + { + ts << ci->recode(str.mid(index,newIndex-index)); // write text before marker + } + else + { + ts << str.mid(index,newIndex-index); // write text before marker + } bool ok; uint entryIndex = str.mid(newIndex+1,matchLen-1).toUInt(&ok); // get marker id TemplateVariant var; @@ -4137,7 +4237,14 @@ class TemplateNodeMarkers : public TemplateNodeCreator } index=newIndex+matchLen; // set index just after marker } - ts << str.right(str.length()-index); // write text after last marker + if (ci->needsRecoding()) + { + ts << ci->recode(str.right(str.length()-index)); // write text after last marker + } + else + { + ts << str.right(str.length()-index); // write text after last marker + } c->pop(); delete it; } @@ -4244,8 +4351,7 @@ class TemplateNodeResource : public TemplateNodeCreator QCString targetFile = m_asExpr->resolve(c).toString(); mkpath(ci,targetFile); if (targetFile.isEmpty()) - { - ci->warn(m_templateName,m_line,"invalid parameter at right side of 'as' for resource command\n"); + { ci->warn(m_templateName,m_line,"invalid parameter at right side of 'as' for resource command\n"); } else { @@ -4266,6 +4372,59 @@ class TemplateNodeResource : public TemplateNodeCreator //---------------------------------------------------------- +/** @brief Class representing the 'encoding' tag in a template */ +class TemplateNodeEncoding : public TemplateNodeCreator +{ + public: + TemplateNodeEncoding(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data) + : TemplateNodeCreator(parser,parent,line) + { + TRACE(("{TemplateNodeEncoding(%s)\n",data.data())); + ExpressionParser ep(parser,line); + if (data.isEmpty()) + { + parser->warn(m_templateName,line,"encoding tag is missing encoding argument"); + m_encExpr = 0; + } + else + { + m_encExpr = ep.parse(data); + } + QStrList stopAt; + stopAt.append("endencoding"); + parser->parse(this,line,stopAt,m_nodes); + parser->removeNextToken(); // skip over endencoding + TRACE(("}TemplateNodeEncoding(%s)\n",data.data())); + } + ~TemplateNodeEncoding() + { + delete m_encExpr; + } + void render(FTextStream &ts, TemplateContext *c) + { + TemplateContextImpl *ci = dynamic_cast(c); + if (ci==0) return; // should not happen + ci->setLocation(m_templateName,m_line); + QCString encStr; + if (m_encExpr) + { + encStr = m_encExpr->resolve(c).toString(); + } + QCString oldEncStr = ci->encoding(); + if (!encStr.isEmpty()) + { + ci->setEncoding(m_templateName,m_line,encStr); + } + m_nodes.render(ts,c); + ci->setEncoding(m_templateName,m_line,oldEncStr); + } + private: + ExprAst *m_encExpr; + TemplateNodeList m_nodes; +}; + +//---------------------------------------------------------- + /** @brief Factory class for creating tag AST nodes found in a template */ class TemplateNodeFactory { @@ -4328,6 +4487,7 @@ static TemplateNodeFactory::AutoRegister autoRefInclu static TemplateNodeFactory::AutoRegister autoRefMarkers("markers"); static TemplateNodeFactory::AutoRegister autoRefTabbing("tabbing"); static TemplateNodeFactory::AutoRegister autoRefResource("resource"); +static TemplateNodeFactory::AutoRegister autoRefEncoding("encoding"); static TemplateNodeFactory::AutoRegister autoRefSpaceless("spaceless"); static TemplateNodeFactory::AutoRegister autoRefIndexEntry("indexentry"); static TemplateNodeFactory::AutoRegister autoRefOpenSubIndex("opensubindex"); @@ -4715,7 +4875,8 @@ void TemplateParser::parse( command=="endrecursetree" || command=="endspaceless" || command=="endmarkers" || command=="endmsg" || command=="endrepeat" || command=="elif" || - command=="endrange" || command=="endtabbing") + command=="endrange" || command=="endtabbing" || + command=="endencoding") { warn(m_templateName,tok->line,"Found tag '%s' without matching start tag",command.data()); } diff --git a/templates/html/htmlhelpindexhhp.tpl b/templates/html/htmlhelpindexhhp.tpl new file mode 100644 index 0000000..5451509 --- /dev/null +++ b/templates/html/htmlhelpindexhhp.tpl @@ -0,0 +1,33 @@ +[OPTIONS] +Compatibility=1.1 +Full-text search=Yes +Contents file=index.hhc +Default Window=main +Default topic=index{{ config.HTML_FILE_EXTENSION }} +Index file=index.hhk +Language={{ tr.langString }} +{% if config.BINARY_TOC %}Binary TOC=YES{% endif %} +{% if config.GENERATE_CHI %}Create CHI file=YES{% endif %} +Title={{ config.PROJECT_NAME }} + +[WINDOWS] +main="My Project","index.hhc","index.hhk","index{{ config.HTML_FILE_EXTENSION }}","index{{ config.HTML_FILE_EXTENSION }}",,,,,0x23520,,0x{% if config.BINARY_TOC %}7{% else %}1{% endif %}0387e,,,,,,,,0 + +[FILES] +{% recursetree index.nav %} +{% if not node.isReference %}{{ node.file }}{{ config.HTML_FILE_EXTENSION }}{% endif %} +{{ children }} +{% endrecursetree %} +tab_a.png +tab_b.png +tab_h.png +tab_s.png +nav_h.png +nav_f.png +bc_s.png +doxygen.png +closed.png +open.png +bdwn.png +sync_on.png +sync_off.png diff --git a/templates/html/htmllayout.tpl b/templates/html/htmllayout.tpl index e609214..9834f67 100644 --- a/templates/html/htmllayout.tpl +++ b/templates/html/htmllayout.tpl @@ -266,6 +266,13 @@ {% endfor %} {% endif %} +{# write html help index #} +{% if config.GENERATE_HTMLHELP %} + {% encoding config.CHM_INDEX_ENCODING|default:'CP1250' %} + {% create 'index.hhp' from 'htmlhelpindexhhp.tpl' %} + {% endencoding %} +{% endif %} + {# write the navigation tree data #} {% if config.GENERATE_TREEVIEW %} {% create 'navtreedata.js' from 'htmljsnavtree.tpl' %} -- cgit v0.12