/***************************************************************************/ /* * Portions Copyright (c) 1999 GMRS Software GmbH * Carl-von-Linde-Str. 38, D-85716 Unterschleissheim, http://www.gmrs.de * All rights reserved. * * Author: Arno Unkrig */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License in the file COPYING for more details. */ /***************************************************************************/ /* * Changes to version 1.2.2 were made by Martin Bayer * Dates and reasons of modifications: * Fre Jun 8 17:43:02 CEST 2001: new method * Wed Jul 2 22:07:12 CEST 2003: ported to g++ 3.3 */ /***************************************************************************/ #include #include #include #include "html.h" #include "HTMLParser.h" #include "cmp_nocase.h" /* ------------------------------------------------------------------------- */ /* * Define some helpers. */ #define define_foreach(T, args, action) \ void foreach args { \ for (T::const_iterator i = l.begin(); i != l.end(); ++i) { \ action; \ } \ } #define pack(T) \ define_foreach(list >, ( \ const list > &l, \ ostream &os, \ ostream_manipulator separator \ ), (*i)->unparse(os, separator)) static pack(Element) static pack(TableCell) static pack(TableRow) static pack(ListItem) static pack(Option) static pack(DefinitionListItem) static pack(Script) static pack(Style) #undef pack /* * Special helper for "const auto_ptr > &". */ static ostream &operator<<(ostream &os, const auto_ptr > &a) { if (a.get()) { const list &al(*a); list::const_iterator i; for (i = al.begin(); i != al.end(); ++i) { os << " " << (*i).first << "=\"" << (*i).second << "\""; } } return os; } /* ------------------------------------------------------------------------- */ /* * Brothers of "endl". */ static ostream &none(ostream &os) { return os; } /* ------------------------------------------------------------------------- */ /* * Some C++ compilers (e.g. EGCS 2.91.66) have problems if all virtual * methods of a class are inline or pure virtual, so we define the virtual * "Element::~Element()", which is the only virtual method, non-inline, * although it is empty. */ Element::~Element() { } /* ------------------------------------------------------------------------- */ void Document::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; head.unparse(os, separator); body.unparse(os, separator); os << "" << separator; } void Head::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (title.get()) { os << "" << separator; title->unparse(os, separator); os << "" << separator; } if (isindex_attributes.get()) { os << "" << std::endl; } if (base_attributes.get()) os << "" << std::endl; foreach(scripts, os, separator); foreach(styles, os, separator); if (meta_attributes.get()) os << "" << std::endl; if (link_attributes.get()) os << "" << std::endl; os << "" << separator; } void Script::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator << text << "" << separator; } void Style::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator << text << "" << separator; } void Body::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void PCData::unparse(ostream &os, ostream_manipulator separator) const { for (string::size_type j = 0; j < text.length(); ++j) { char c = text[j]; switch (((int) c) & 255) { case LATIN1_nbsp: os << " "; break; case '&': os << "&"; break; case '<': os << "<"; break; case '>': os << ">"; break; case '"': os << """; break; default: if (c & 0x80) { os << "&#" << (((int) c) & 255) << ";"; } else { os << c; } break; } } os << separator; } void Heading::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void Paragraph::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (texts.get()) foreach(*texts, os, separator); os << "

" << separator; } void Image::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void Applet::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void Param::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void Division::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (body_content.get()) foreach(*body_content, os, separator); os << "" << separator; } void Center::unparse(ostream &os, ostream_manipulator separator) const { os << "
" << separator; if (body_content.get()) foreach(*body_content, os, separator); os << "
" << separator; } void BlockQuote::unparse(ostream &os, ostream_manipulator separator) const { os << "
" << separator; if (content.get()) foreach(*content, os, separator); os << "
" << separator; } void Address::unparse(ostream &os, ostream_manipulator separator) const { os << "
" << separator; if (content.get()) foreach(*content, os, separator); os << "
" << separator; } void Form::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void Preformatted::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (texts.get()) { foreach(*texts, os, none); os << separator; } os << "" << separator; } void HorizontalRule::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void Input::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void Option::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (pcdata.get()) pcdata->unparse(os, separator); os << "" << std::endl; } void Select::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << std::endl; } void TextArea::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (pcdata.get()) pcdata->unparse(os, separator); os << "" << std::endl; } /* ------------------------------------------------------------------------- */ void OrderedList::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (items.get()) foreach(*items, os, separator); os << "" << separator; } void UnorderedList::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (items.get()) foreach(*items, os, separator); os << "" << separator; } void Dir::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (items.get()) foreach(*items, os, separator); os << "" << separator; } void Menu::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (items.get()) foreach(*items, os, separator); os << "" << separator; } void ListNormalItem::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (flow.get()) foreach(*flow, os, separator); os << "" << separator; } void ListBlockItem::unparse(ostream &os, ostream_manipulator separator) const { if (block.get()) block->unparse(os, separator); } /* ------------------------------------------------------------------------- */ void DefinitionList::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (items.get()) foreach(*items, os, separator); os << "" << separator; } void TermName::unparse(ostream &os, ostream_manipulator separator) const { os << "
" << separator; if (flow.get()) foreach(*flow, os, separator); os << "
" << separator; } void TermDefinition::unparse(ostream &os, ostream_manipulator separator) const { os << "
" << separator; if (flow.get()) foreach(*flow, os, separator); os << "
" << separator; } /* ------------------------------------------------------------------------- */ void Table::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (caption.get()) caption->unparse(os, separator); if (rows.get()) foreach(*rows, os, separator); os << "" << separator; } void NoBreak::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void Font::unparse(ostream &os, ostream_manipulator separator) const { const char *tag = ( attribute == HTMLParser::TT ? "TT" : attribute == HTMLParser::I ? "I" : attribute == HTMLParser::B ? "B" : attribute == HTMLParser::U ? "U" : attribute == HTMLParser::STRIKE ? "STRIKE" : attribute == HTMLParser::BIG ? "BIG" : attribute == HTMLParser::SMALL ? "SMALL" : attribute == HTMLParser::SUB ? "SUB" : attribute == HTMLParser::SUP ? "SUP" : "???" ); os << "<" << tag << ">" << separator; if (texts.get()) foreach(*texts, os, separator); os << "" << separator; } void Phrase::unparse(ostream &os, ostream_manipulator separator) const { const char *tag = ( attribute == HTMLParser::EM ? "EM" : attribute == HTMLParser::STRONG ? "STRONG" : attribute == HTMLParser::DFN ? "DFN" : attribute == HTMLParser::CODE ? "CODE" : attribute == HTMLParser::SAMP ? "SAMP" : attribute == HTMLParser::KBD ? "KBD" : attribute == HTMLParser::VAR ? "VAR" : attribute == HTMLParser::CITE ? "CITE" : "???" ); os << "<" << tag << ">" << separator; if (texts.get()) foreach(*texts, os, separator); os << "" << separator; } void Anchor::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (texts.get()) foreach(*texts, os, separator); os << "" << separator; } void BaseFont::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void LineBreak::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; } void Map::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (areas.get()) { const list > > &al(*areas); list > >::const_iterator i; for (i = al.begin(); i != al.end(); ++i) { os << "" << separator; } } os << "" << separator; } void Font2::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (elements.get()) foreach(*elements, os, separator); os << "" << separator; } void TableRow::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (cells.get()) foreach(*cells, os, separator); os << "" << separator; } void TableCell::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void TableHeadingCell::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (content.get()) foreach(*content, os, separator); os << "" << separator; } void Caption::unparse(ostream &os, ostream_manipulator separator) const { os << "" << separator; if (texts.get()) foreach(*texts, os, separator); os << "" << separator; } /* ------------------------------------------------------------------------- */ string get_attribute( const list *as, const char *name, const char *dflt ) { if (as) { list::const_iterator i; for (i = as->begin(); i != as->end(); ++i) { if (cmp_nocase((*i).first, name) == 0) return string((*i).second); } } return string(dflt); } // *exists is set to false if attribute *name does not exist - Johannes Geiger string get_attribute( const list *as, const char *name, bool *exists ) { *exists = true; if (as) { list::const_iterator i; for (i = as->begin(); i != as->end(); ++i) { if (cmp_nocase((*i).first, name) == 0) return string((*i).second); } } *exists = false; return string(""); } int get_attribute( const list *as, const char *name, int dflt ) { if (as) { list::const_iterator i; for (i = as->begin(); i != as->end(); ++i) { if (cmp_nocase((*i).first, name) == 0) return atoi((*i).second.c_str()); } } return dflt; } int get_attribute( const list *as, const char *name, int dflt, const char *s1, int v1, ... ) { if (as) { list::const_iterator i; for (i = as->begin(); i != as->end(); ++i) { if (cmp_nocase((*i).first, name) == 0) { const char *s = s1; int v = v1; va_list va; va_start(va, v1); for (;;) { if (cmp_nocase(s, (*i).second) == 0) break; s = va_arg(va, const char *); if (!s) { v = dflt; break; } v = va_arg(va, int); } va_end(va); return v; } } } return dflt; } int get_attribute( const list *as, const char *name, // Attribute name const char *dflt1, // If attribute not specified int dflt2, // If string value does not match s1, ... const char *s1, int v1, ... ) { if (as) { list::const_iterator i; for (i = as->begin(); i != as->end(); ++i) { if (cmp_nocase((*i).first, name) == 0) { dflt1 = (*i).second.c_str(); break; } } } if (!dflt1) return dflt2; const char *s = s1; int v = v1; va_list va; va_start(va, v1); for (;;) { if (cmp_nocase(s, dflt1) == 0) break; s = va_arg(va, const char *); if (!s) break; v = va_arg(va, int); } va_end(va); return s ? v : dflt2; } /* ------------------------------------------------------------------------- */