summaryrefslogtreecommitdiffstats
path: root/src/template.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/template.cpp')
-rw-r--r--src/template.cpp187
1 files changed, 174 insertions, 13 deletions
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<TemplateStruct> m_indices;
QDict< QStack<TemplateVariant> > 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<TemplateContextImpl*>(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<TemplateNodeIf>
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<TemplateNodeCycle>
}
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<TemplateNodeMarkers>
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<TemplateNodeMarkers>
}
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<TemplateNodeResource>
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<TemplateNodeResource>
//----------------------------------------------------------
+/** @brief Class representing the 'encoding' tag in a template */
+class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding>
+{
+ public:
+ TemplateNodeEncoding(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
+ : TemplateNodeCreator<TemplateNodeEncoding>(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<TemplateContextImpl*>(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<TemplateNodeInclude> autoRefInclu
static TemplateNodeFactory::AutoRegister<TemplateNodeMarkers> autoRefMarkers("markers");
static TemplateNodeFactory::AutoRegister<TemplateNodeTabbing> autoRefTabbing("tabbing");
static TemplateNodeFactory::AutoRegister<TemplateNodeResource> autoRefResource("resource");
+static TemplateNodeFactory::AutoRegister<TemplateNodeEncoding> autoRefEncoding("encoding");
static TemplateNodeFactory::AutoRegister<TemplateNodeSpaceless> autoRefSpaceless("spaceless");
static TemplateNodeFactory::AutoRegister<TemplateNodeIndexEntry> autoRefIndexEntry("indexentry");
static TemplateNodeFactory::AutoRegister<TemplateNodeOpenSubIndex> 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());
}