#include "html.hpp" #include TexoHTMLProducer::TexoHTMLProducer(TexoExporter &exporter): TexoProducer(exporter) {} void TexoHTMLProducer::Put(const Texo &piece) { switch (piece.type) { case Texo::character: exporter.Put(piece.c); break; case Texo::paragraph_begin: exporter.PutStr("

"); break; case Texo::paragraph_end: exporter.PutStr("

"); break; case Texo::newline: exporter.PutStr("
"); break; case Texo::bold_begin: exporter.PutStr(""); break; case Texo::bold_end: exporter.PutStr(""); break; case Texo::italic_begin: exporter.PutStr(""); break; case Texo::italic_end: exporter.PutStr(""); break; case Texo::strike_begin: exporter.PutStr(""); break; case Texo::strike_end: exporter.PutStr(""); break; case Texo::underline_begin: exporter.PutStr(""); break; case Texo::underline_end: exporter.PutStr(""); break; case Texo::link_begin: BeginLink(piece); break; case Texo::link_end: exporter.PutStr(""); break; case Texo::image: Image(piece); break; default: break; } } void TexoHTMLProducer::BeginLink(const Texo &piece) { exporter.PutStr("'); } void TexoHTMLProducer::Image(const Texo &piece) { exporter.PutStr(""); } TexoHTMLStack::TexoHTMLStack(): next(0) {} TexoHTMLStack::~TexoHTMLStack() { if (next) { while (next != this) { Pop(); } } } void TexoHTMLStack::Push(Texo::Type tag) { if (next) { TexoHTMLStack *buf = next; next = new TexoHTMLStack; next->next = buf; next->tag = this->tag; } else { next = this; } this->tag = tag; } Texo::Type TexoHTMLStack::Pop() { if (next) { Texo::Type res = tag; if (next != this) { TexoHTMLStack *buf = next; tag = next->tag; next = next->next; delete buf; } else { next = 0; } return res; } else { return Texo::character; } } TexoHTMLImporter::TexoHTMLImporter(TexoProducer &producer, bool is_autoclose): TexoImporter(producer), state(text), is_closing(0), tag(Texo::character), readed(0), readed_len(0), readed_size(0), is_autoclose(is_autoclose) {} TexoHTMLImporter::~TexoHTMLImporter() { ReadedClear(); } void TexoHTMLImporter::Put(const char c) { if (c) { switch (state) { case text: state = Text(c); break; case tag_open: state = TagOpen(c); break; case tag_name: state = TagName(c); break; case tag_param_skip: state = TagParamSkip(c); break; case tag_param_pre: state = TagParamPre(c); break; case tag_param: state = TagParam(c); break; case tag_param_post: state = TagParamPost(c); break; case tag_param_value_pre: state = TagParamValuePre(c); break; case tag_param_value: state = TagParamValue(c); break; case tag_param_value_quoted: state = TagParamValueQuoted(c); break; default: break; } } else { tag = Texo::character; Close(); } } TexoHTMLImporter::State TexoHTMLImporter::Text(const char c) { State st = text; switch (c) { case '<': st = tag_open; break; case '>': producer.PutStr(">"); break; default: producer.Put(Texo(c)); break; } return st; } TexoHTMLImporter::State TexoHTMLImporter::TagOpen(const char c) { State st = tag_open; switch (c) { case '/': is_closing = 1; break; case ' ': st = text; producer.PutStr("<"); if (is_closing) { producer.Put(Texo('/')); } producer.Put(Texo(' ')); break; case '>': st = text; producer.PutStr("<"); if (is_closing) { producer.Put(Texo('/')); } producer.PutStr(">"); break; default: st = tag_name; ReadedAdd(c); break; } return st; } TexoHTMLImporter::State TexoHTMLImporter::TagName(const char c) { State st = tag_name; switch (c) { case ' ': st = tag_param_skip; SetTag(); break; case '/': st = tag_param_skip; SetTag(); break; case '>': st = text; SetTag(); if (tag) { if (is_closing) { Close(); } else { producer.Put(Texo(tag)); } } is_closing = false; break; default: ReadedAdd(c); break; } return st; } TexoHTMLImporter::State TexoHTMLImporter::TagParamSkip(const char c) { State st = tag_param_skip; switch (c) { case '>': st = text; if (tag) { if (is_closing) { Close(); } else { producer.Put(Texo(tag)); } } is_closing = false; break; default: break; } return st; } TexoHTMLImporter::State TexoHTMLImporter::TagParamPre(const char c) { return text; } TexoHTMLImporter::State TexoHTMLImporter::TagParam(const char c) { return text; } TexoHTMLImporter::State TexoHTMLImporter::TagParamPost(const char c) { return text; } TexoHTMLImporter::State TexoHTMLImporter::TagParamValuePre(const char c) { return text; } TexoHTMLImporter::State TexoHTMLImporter::TagParamValue(const char c) { return text; } TexoHTMLImporter::State TexoHTMLImporter::TagParamValueQuoted(const char c) { return text; } void TexoHTMLImporter::Close() { Texo::Type current = opened.Pop(); while ((current != tag) && current) { producer.Put(Texo(current)); current = opened.Pop(); } if (current) { producer.Put(Texo(current)); } } void TexoHTMLImporter::SetTag() { if (!strcmp(readed, "a")) { if (is_closing) { tag = Texo::link_end; } else { tag = Texo::link_begin; opened.Push(Texo::link_end); } } else if (!strcmp(readed, "img")) { tag = Texo::image; } else if (!strcmp(readed, "b")) { if (is_closing) { tag = Texo::bold_end; } else { tag = Texo::bold_begin; opened.Push(Texo::bold_end); } } else if (!strcmp(readed, "i")) { if (is_closing) { tag = Texo::italic_end; } else { tag = Texo::italic_begin; opened.Push(Texo::italic_end); } } else if (!strcmp(readed, "del")) { if (is_closing) { tag = Texo::strike_end; } else { tag = Texo::strike_begin; opened.Push(Texo::strike_end); } } else if (!strcmp(readed, "ins")) { if (is_closing) { tag = Texo::underline_end; } else { tag = Texo::underline_begin; opened.Push(Texo::underline_end); } } else if (!strcmp(readed, "p")) { if (is_closing) { tag = Texo::paragraph_end; } else { tag = Texo::paragraph_begin; opened.Push(Texo::paragraph_end); } } else if (!strcmp(readed, "br")) { tag = Texo::newline; } else { tag = Texo::character; } ReadedClear(); } void TexoHTMLImporter::ReadedAdd(const char c) { if (readed_size == 0) { readed_size = 2; readed = new char[readed_size]; } else if (readed_size - 1 == readed_len) { char *buf = readed; readed_size = readed_size << 1; readed = new char[readed_size]; for (int i = 0; i < readed_len; ++i) { readed[i] = buf[i]; } delete buf; } ++readed_len; readed[readed_len - 1] = c; readed[readed_len] = 0; } void TexoHTMLImporter::ReadedClear() { readed_len = 0; readed_size = 0; if (readed) { delete readed; readed = 0; } }