// Copyright 1998,1999 Zanshin Inc.
// The contents of this file are subject to the Zanshin Public License Version
// 1.0 (the "License"); you may not use this file except in compliance with the
// License. You should have received a copy of the License with Latte; see
// the file COPYING. You may also obtain a copy of the License at
// .
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is Latte.
//
// The Initial Developer of the Original Code is Zanshin, Inc.
#include
#include
#include
#include
#include
#include
using namespace std;
static bool in_pre = 0;
static bool in_html = 0;
void
LatteHtml_PreObj::visit(Latte_Visitor &visitor)
{
Restorer in_pre_restorer(in_pre);
in_pre = 1;
nested_obj()->visit(visitor);
}
Refcounter
LatteHtml_PreObj::do_eval(Latte_Activation &activation)
{
if (self_evaluating())
return Refcounter(this);
return Refcounter(new
LatteHtml_PreObj(*(nested_obj()->eval(activation))));
}
void
LatteHtml_HtmlObj::visit(Latte_Visitor &visitor)
{
Restorer in_html_restorer(in_html);
in_html = 1;
nested_obj()->visit(visitor);
}
Refcounter
LatteHtml_HtmlObj::do_eval(Latte_Activation &activation)
{
if (self_evaluating())
return Refcounter(this);
return Refcounter(new
LatteHtml_HtmlObj(*(nested_obj()->eval(activation))));
}
class PreOp : public Latte_Operator {
public:
const shstring &name() const { static const shstring n = "_pre"; return n; }
protected:
Refcounter apply(const Latte_Wstate &wstate,
const Latte_FileLoc &fileloc,
const Latte_List::const_iterator &args,
const Latte_List::const_iterator &args_end,
Latte_Activation &activation) const {
Refcounter result_list(new Latte_List);
for (Latte_List::const_iterator i = args; i != args_end; ++i)
result_list->push_back((*i)->eval(activation));
return Refcounter(new
LatteHtml_PreObj(*(Latte_WsNode::wrap(*result_list,
wstate))));
}
};
class HtmlOp : public Latte_Operator {
public:
const shstring &name() const { static const shstring n = "html"; return n; }
protected:
Refcounter apply(const Latte_Wstate &wstate,
const Latte_FileLoc &fileloc,
const Latte_List::const_iterator &args,
const Latte_List::const_iterator &args_end,
Latte_Activation &activation) const {
Refcounter result_list(new Latte_List);
for (Latte_List::const_iterator i = args; i != args_end; ++i)
result_list->push_back((*i)->eval(activation));
Refcounter wsnode(new Latte_WsNode(*result_list, wstate));
return Refcounter(new
LatteHtml_HtmlObj(*(Latte_WsNode::wrap(*result_list,
wstate))));
}
};
void
LatteHtml_HtmlVisitor::visit_str(Latte_Str &str)
{
static bool ever_called = 0;
static bool p_begun = 0;
const Latte_Wstate &ws = suggest_wstate(str.wstate());
if (ever_called) {
bool do_p = (!in_pre && (ws.newlines() > 1));
if (do_p && p_begun && m_close_par)
m_out << "
";
m_out << ws;
if (do_p) {
m_out << "";
p_begun = 1;
}
}
ever_called = 1;
if (in_html)
m_out << str.str();
else
for (Latte_Str::const_iterator i = str.begin(); i != str.end(); ++i) {
const char &c = *i;
switch (c) {
case '<':
m_out << "<";
break;
case '>':
m_out << ">";
break;
case '&':
m_out << "&";
break;
case '"':
m_out << """;
break;
default:
m_out << c;
break;
}
}
}
void
latte_html(const char *lang,
bool strict, bool fragment, bool no_default, bool close_par,
unsigned long log_flags,
const deque::const_iterator &loads_begin,
const deque::const_iterator &loads_end,
const char *filename, istream &in, ostream &out)
{
srandom(getpid() ^ time(0)); // should the UI do this?
latte_init(1);
Latte_Reader reader(in, filename);
latte_log_flags = log_flags;
reader.install_standard_definitions();
reader.define_global("__FILE__",
Refcounter(new
Latte_Str(Latte_Wstate(),
Latte_FileLoc(),
filename)));
reader.define_global("html", Refcounter(new HtmlOp));
reader.define_global("_pre", Refcounter(new PreOp));
reader.define_global("strict-html4", strict ? latte_true() : latte_false());
if (!no_default) {
latte_load_library("standard", reader.global_activation());
latte_load_library("html", reader.global_activation());
}
for (deque::const_iterator i = loads_begin;
i != loads_end;
++i)
latte_load_library(*i, reader.global_activation());
LatteHtml_HtmlVisitor visitor(out, close_par);
if (!fragment) {
out << ""
<< endl;
out << "" << endl;
out << "" << endl;
out << "" << endl;
}
reader.process(visitor);
#if 0
if (!reader.processed()) {
const Latte_Obj &unprocessed = reader.unprocessed();
const Latte_Tangible *tangible = unprocessed.as_tangible();
const Latte_Group *group = unprocessed.as_group();
const Latte_Assignment *assignment = unprocessed.as_assignment();
if (group)
throw Latte_Reader::IncompleteGroup(group->fileloc());
if (assignment)
throw Latte_Reader::IncompleteAssignment(assignment->fileloc());
if (tangible)
throw Latte_Reader::Incomplete(tangible->fileloc());
throw Latte_Reader::Incomplete(Latte_FileLoc());
}
#endif
out << endl;
if (!fragment)
out << "" << endl;
}