📄 html.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: html.cpp,v $ * PRODUCTION Revision 1000.4 2004/06/01 19:15:26 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.103 * PRODUCTION * =========================================================================== *//* $Id: html.cpp,v 1000.4 2004/06/01 19:15:26 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Lewis Geer * */#include <ncbi_pch.hpp>#include <html/html.hpp>#include <html/htmlhelper.hpp>#include <html/indentstream.hpp>#include <html/html_exception.hpp>#include <errno.h>#include <string.h>BEGIN_NCBI_SCOPE/// Tag delimitersconst char* kTagStart = "<@"; ///< Tag start.const char* kTagEnd = "@>"; ///< Tag end.const char* kTagStartEnd = "</@"; ///< Tag start in the end of ///< block definition.#define CHECK_STREAM_WRITE(out) \ if ( !out ) { \ int x_errno = errno; \ string x_err("write to stream failed"); \ if (x_errno != 0) { \ const char* x_strerror = strerror(x_errno); \ if ( !x_strerror ) { \ x_strerror = "Error code is out of range"; \ } \ string x_strerrno = NStr::IntToString(x_errno); \ x_err += " {errno=" + x_strerrno + ',' + x_strerror + '}'; \ } \ NCBI_THROW(CHTMLException, eWrite, x_err); \ }static string s_GenerateNodeInternalName(const string& basename, const string& v1, const string& v2 = kEmptyStr){ string name(basename); if ( !v1.empty() ) { name += "(\"" + v1.substr(0,10) + "\""; if ( !v2.empty() ) { name += "|\"" + v2.substr(0,10) + "\""; } name += ")"; } return name;}// CHTMLNodeCHTMLNode::~CHTMLNode(void){ return;}CHTMLNode* CHTMLNode::SetClass(const string& class_name){ SetOptionalAttribute("class", class_name); return this;}CHTMLNode* CHTMLNode::SetId(const string& class_name){ SetOptionalAttribute("id", class_name); return this;}CHTMLNode* CHTMLNode::SetWidth(int width){ SetAttribute("width", width); return this;}CHTMLNode* CHTMLNode::SetHeight(int height){ SetAttribute("height", height); return this;}CHTMLNode* CHTMLNode::SetWidth(const string& width){ SetOptionalAttribute("width", width); return this;}CHTMLNode* CHTMLNode::SetHeight(const string& height){ SetOptionalAttribute("height", height); return this;}CHTMLNode* CHTMLNode::SetSize(int size){ SetAttribute("size", size); return this;}CHTMLNode* CHTMLNode::SetAlign(const string& align){ SetOptionalAttribute("align", align); return this;}CHTMLNode* CHTMLNode::SetVAlign(const string& align){ SetOptionalAttribute("valign", align); return this;}CHTMLNode* CHTMLNode::SetColor(const string& color){ SetOptionalAttribute("color", color); return this;}CHTMLNode* CHTMLNode::SetBgColor(const string& color){ SetOptionalAttribute("bgcolor", color); return this;}CHTMLNode* CHTMLNode::SetNameAttribute(const string& name){ SetAttribute("name", name); return this;}const string& CHTMLNode::GetNameAttribute(void) const{ return GetAttribute("name");}CHTMLNode* CHTMLNode::SetAccessKey(char key){ SetAttribute("accesskey", string(1, key)); return this;}CHTMLNode* CHTMLNode::SetTitle(const string& title){ SetAttribute("title", title); return this;}CHTMLNode* CHTMLNode::SetStyle(const string& style){ SetAttribute("style", style); return this;}void CHTMLNode::AppendPlainText(const string& appendstring, bool noEncode){ if ( !appendstring.empty() ) { AppendChild(new CHTMLPlainText(appendstring, noEncode)); }}void CHTMLNode::AppendPlainText(const char* appendstring, bool noEncode){ if ( appendstring && *appendstring ) { AppendChild(new CHTMLPlainText(appendstring, noEncode)); }}void CHTMLNode::AppendHTMLText(const string& appendstring){ if ( !appendstring.empty() ) { AppendChild(new CHTMLText(appendstring)); }}void CHTMLNode::AppendHTMLText(const char* appendstring){ if ( appendstring && *appendstring ) { AppendChild(new CHTMLText(appendstring)); }}string CHTMLNode::GetEventHandlerName(const EHTML_EH_Attribute name) const{ switch (name) { case eHTML_EH_Blur: return "onBlur"; case eHTML_EH_Change: return "onChange"; case eHTML_EH_Click: return "onClick"; case eHTML_EH_DblClick: return "onDblClick"; case eHTML_EH_Focus: return "onFocus"; case eHTML_EH_Load: return "onLoad"; case eHTML_EH_Unload: return "onUnload"; case eHTML_EH_MouseDown: return "onMouseDown"; case eHTML_EH_MouseUp: return "onMouseUp"; case eHTML_EH_MouseMove: return "onMouseMove"; case eHTML_EH_MouseOver: return "onMouseOver"; case eHTML_EH_MouseOut: return "onMouseOut"; case eHTML_EH_Select: return "onSelect"; case eHTML_EH_Submit: return "onSubmit"; case eHTML_EH_KeyDown: return "onKeyDown"; case eHTML_EH_KeyPress: return "onKeyPress"; case eHTML_EH_KeyUp: return "onKeyUp"; } _TROUBLE; return kEmptyStr;}void CHTMLNode::SetEventHandler(const EHTML_EH_Attribute event, const string& value){ if ( value.empty() ) { return; } SetAttribute(GetEventHandlerName(event), value);}void CHTMLNode::AttachPopupMenu(const CHTMLPopupMenu* menu, EHTML_EH_Attribute event){ if ( !menu ) { return; } const string kStopEvent = " return false;"; switch (menu->GetType()) { case CHTMLPopupMenu::eSmith: SetEventHandler(event, menu->ShowMenu() + kStopEvent); return; case CHTMLPopupMenu::eKurdin: case CHTMLPopupMenu::eKurdinConf: SetEventHandler(event, menu->ShowMenu() + kStopEvent); SetEventHandler(eHTML_EH_MouseOut, menu->HideMenu()); return; case CHTMLPopupMenu::eKurdinSide: AppendHTMLText(menu->ShowMenu()); return; } _TROUBLE;}// <@XXX@> mapping tag nodeCHTMLTagNode::CHTMLTagNode(const char* name) : CParent(name){ return;}CHTMLTagNode::CHTMLTagNode(const string& name) : CParent(name){ return;}CHTMLTagNode::~CHTMLTagNode(void){ return;}CNcbiOstream& CHTMLTagNode::PrintChildren(CNcbiOstream& out, TMode mode){ CNodeRef node = MapTagAll(GetName(), mode); if ( node ) { node->Print(out, mode); } return out;}// Dual text node.CHTMLDualNode::CHTMLDualNode(const char* html, const char* plain) : CParent(s_GenerateNodeInternalName("dualnode", html, plain)){ AppendChild(new CHTMLText(html)); m_Plain = plain;}CHTMLDualNode::CHTMLDualNode(CNCBINode* child, const char* plain) : CParent(s_GenerateNodeInternalName("dualnode", "[node]", plain)){ AppendChild(child); m_Plain = plain;}CHTMLDualNode::~CHTMLDualNode(void){ return;}CNcbiOstream& CHTMLDualNode::PrintChildren(CNcbiOstream& out, TMode mode){ if ( mode == ePlainText ) { out << m_Plain; CHECK_STREAM_WRITE(out); return out; } else { return CParent::PrintChildren(out, mode); }}// plain text nodeCHTMLPlainText::CHTMLPlainText(const char* text, bool noEncode) : CNCBINode(s_GenerateNodeInternalName("plaintext", text)), m_NoEncode(noEncode), m_Text(text){ return;}CHTMLPlainText::CHTMLPlainText(const string& text, bool noEncode) : CNCBINode(s_GenerateNodeInternalName("plaintext", text)), m_NoEncode(noEncode), m_Text(text){ return;}CHTMLPlainText::~CHTMLPlainText(void){ return;}CNcbiOstream& CHTMLPlainText::PrintBegin(CNcbiOstream& out, TMode mode){ if (mode == ePlainText || NoEncode()) { out << GetText(); } else { out << CHTMLHelper::HTMLEncode(GetText()); } CHECK_STREAM_WRITE(out); return out;}// text nodeCHTMLText::CHTMLText(const string& text) : CParent(s_GenerateNodeInternalName("htmltext", text)), m_Text(text){ return;}CHTMLText::CHTMLText(const char* text) : CParent(s_GenerateNodeInternalName("htmltext", text)), m_Text(text){ return;}CHTMLText::~CHTMLText(void){ return;}static SIZE_TYPE s_Find(const string& s, const char* target, SIZE_TYPE start = 0){ // Return s.find(target); // Some implementations of string::find call memcmp at every // possible position, which is way too slow. if ( start >= s.size() ) { return NPOS; } const char* cstr = s.c_str(); const char* p = strstr(cstr + start, target); return p ? p - cstr : NPOS;}CNcbiOstream& CHTMLText::x_PrintBegin(CNcbiOstream& out, TMode mode, const string& s) const{ if ( mode == ePlainText ) { out << CHTMLHelper::StripHTML(s); } else { out << s; } CHECK_STREAM_WRITE(out); return out;}CNcbiOstream& CHTMLText::PrintBegin(CNcbiOstream& out, TMode mode){ const string& text = GetText(); SIZE_TYPE tagStart = s_Find(text, kTagStart); if ( tagStart == NPOS ) { return x_PrintBegin(out, mode, text); } SIZE_TYPE tag_start_size = strlen(kTagStart); SIZE_TYPE tag_end_size = strlen(kTagEnd); x_PrintBegin(out, mode, text.substr(0, tagStart)); SIZE_TYPE last = tagStart; do { SIZE_TYPE tagNameStart = tagStart + tag_start_size; SIZE_TYPE tagNameEnd = s_Find(text, kTagEnd, tagNameStart); if ( tagNameEnd == NPOS ) { // tag not closed NCBI_THROW(CHTMLException, eTextUnclosedTag, "tag not closed"); } else { // tag found if ( last != tagStart ) { x_PrintBegin(out, mode, text.substr(last, tagStart - last)); } string name = text.substr(tagNameStart,tagNameEnd-tagNameStart); // Resolve and repeat tag for (;;) { CNodeRef tag = MapTagAll(name, mode); if ( tag ) { tag->Print(out, mode); if ( tag->NeedRepeatTag() ) { RepeatTag(false); continue; } } break; } last = tagNameEnd + tag_end_size; tagStart = s_Find(text, kTagStart, last); } } while ( tagStart != NPOS ); if ( last != text.size() ) { x_PrintBegin(out, mode, text.substr(last)); } return out;}CHTMLOpenElement::~CHTMLOpenElement(void){ return;}CNcbiOstream& CHTMLOpenElement::PrintBegin(CNcbiOstream& out, TMode mode){ if ( mode != ePlainText ) { out << '<' << m_Name; if ( HaveAttributes() ) { for ( TAttributes::const_iterator i = Attributes().begin(); i != Attributes().end(); ++i ) { out << ' ' << i->first; CHECK_STREAM_WRITE(out); if ( !i->second.IsOptional() || !i->second.GetValue().empty() ) { out << "=\"" << i->second.GetValue() << '"'; } } } if ( m_NoWrap ) { out << " nowrap"; } out << '>'; CHECK_STREAM_WRITE(out); } return out;}CHTMLInlineElement::~CHTMLInlineElement(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -