1 /* $Id: html.cpp 435421 2014-05-15 19:29:47Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Lewis Geer, Eugene Vasilchenko, Vladimir Ivanov
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31 #include <html/html.hpp>
32 #include <html/htmlhelper.hpp>
33 #include <html/indentstream.hpp>
34 #include <html/html_exception.hpp>
35 #include <html/error_codes.hpp>
36 #include <errno.h>
37 #include <string.h>
38
39
40 #define NCBI_USE_ERRCODE_X Html_Lib
41
42
43 BEGIN_NCBI_SCOPE
44
45
46 /// Tag delimiters
47 const char* kTagStart = "<@"; ///< Tag start
48 const char* kTagEnd = "@>"; ///< Tag end
49 const SIZE_TYPE kTagStartLen = 2;
50
51
52 #define INIT_STREAM_WRITE \
53 errno = 0
54
55 #define CHECK_STREAM_WRITE(out) \
56 if ( !out ) { \
57 int x_errno = errno; \
58 string x_err("write to stream failed"); \
59 if (x_errno != 0) { \
60 const char* x_strerror = strerror(x_errno); \
61 if ( !x_strerror ) { \
62 x_strerror = "Error code is out of range"; \
63 } \
64 string x_strerrno = NStr::IntToString(x_errno); \
65 x_err += " {errno=" + x_strerrno + ',' + x_strerror + '}'; \
66 } \
67 NCBI_THROW(CHTMLException, eWrite, x_err); \
68 }
69
70
s_GenerateNodeInternalName(const string & basename,const string & v1,const string & v2=kEmptyStr)71 static string s_GenerateNodeInternalName(const string& basename,
72 const string& v1,
73 const string& v2 = kEmptyStr)
74 {
75 string name(basename);
76 if ( !v1.empty() ) {
77 name += "(\"" + v1.substr(0,10) + "\"";
78 if ( !v2.empty() ) {
79 name += "|\"" + v2.substr(0,10) + "\"";
80 }
81 name += ")";
82 }
83 return name;
84 }
85
86
s_Find(const string & s,const char * target,SIZE_TYPE start=0)87 static SIZE_TYPE s_Find(const string& s, const char* target,
88 SIZE_TYPE start = 0)
89 {
90 // Return s.find(target);
91 // Some implementations of string::find call memcmp at every
92 // possible position, which is way too slow.
93 if ( start >= s.size() ) {
94 return NPOS;
95 }
96 const char* cstr = s.c_str();
97 const char* p = strstr(cstr + start, target);
98 return p ? p - cstr : NPOS;
99 }
100
101
102 // CHTMLNode
103
~CHTMLNode(void)104 CHTMLNode::~CHTMLNode(void)
105 {
106 return;
107 }
108
GetEventHandlerName(const EHTML_EH_Attribute name) const109 string CHTMLNode::GetEventHandlerName(const EHTML_EH_Attribute name) const
110 {
111 switch (name) {
112 case eHTML_EH_Blur:
113 return "onblur";
114 case eHTML_EH_Change:
115 return "onchange";
116 case eHTML_EH_Click:
117 return "onclick";
118 case eHTML_EH_DblClick:
119 return "ondblclick";
120 case eHTML_EH_Focus:
121 return "onfocus";
122 case eHTML_EH_Load:
123 return "onload";
124 case eHTML_EH_Unload:
125 return "onunload";
126 case eHTML_EH_MouseDown:
127 return "onmousedown";
128 case eHTML_EH_MouseUp:
129 return "onmouseup";
130 case eHTML_EH_MouseMove:
131 return "onmousemove";
132 case eHTML_EH_MouseOver:
133 return "onmouseover";
134 case eHTML_EH_MouseOut:
135 return "onmouseout";
136 case eHTML_EH_Select:
137 return "onselect";
138 case eHTML_EH_Submit:
139 return "onsubmit";
140 case eHTML_EH_KeyDown:
141 return "onkeydown";
142 case eHTML_EH_KeyPress:
143 return "onkeypress";
144 case eHTML_EH_KeyUp:
145 return "onkeyup";
146 }
147 _TROUBLE;
148 return kEmptyStr;
149 }
150
151
SetEventHandler(const EHTML_EH_Attribute event,const string & value)152 void CHTMLNode::SetEventHandler(const EHTML_EH_Attribute event,
153 const string& value)
154 {
155 if ( value.empty() ) {
156 return;
157 }
158 SetAttribute(GetEventHandlerName(event), value);
159 }
160
161
162 // <@XXX@> mapping tag node
163
CHTMLTagNode(const char * name)164 CHTMLTagNode::CHTMLTagNode(const char* name)
165 : CParent(name)
166 {
167 return;
168 }
169
CHTMLTagNode(const string & name)170 CHTMLTagNode::CHTMLTagNode(const string& name)
171 : CParent(name)
172 {
173 return;
174 }
175
~CHTMLTagNode(void)176 CHTMLTagNode::~CHTMLTagNode(void)
177 {
178 return;
179 }
180
PrintChildren(CNcbiOstream & out,TMode mode)181 CNcbiOstream& CHTMLTagNode::PrintChildren(CNcbiOstream& out, TMode mode)
182 {
183 CNodeRef node = MapTagAll(GetName(), mode);
184 if ( node ) {
185 node->Print(out, mode);
186 }
187 return out;
188 }
189
190
191 // Dual text node.
192
CHTMLDualNode(const char * html,const char * plain)193 CHTMLDualNode::CHTMLDualNode(const char* html, const char* plain)
194 : CParent(s_GenerateNodeInternalName("dualnode", html, plain))
195 {
196 AppendChild(new CHTMLText(html));
197 m_Plain = plain;
198 }
199
CHTMLDualNode(CNCBINode * child,const char * plain)200 CHTMLDualNode::CHTMLDualNode(CNCBINode* child, const char* plain)
201 : CParent(s_GenerateNodeInternalName("dualnode", "[node]", plain))
202 {
203 AppendChild(child);
204 m_Plain = plain;
205 }
206
~CHTMLDualNode(void)207 CHTMLDualNode::~CHTMLDualNode(void)
208 {
209 return;
210 }
211
PrintChildren(CNcbiOstream & out,TMode mode)212 CNcbiOstream& CHTMLDualNode::PrintChildren(CNcbiOstream& out, TMode mode)
213 {
214 switch (mode) {
215 case ePlainText:
216 INIT_STREAM_WRITE;
217 out << m_Plain;
218 CHECK_STREAM_WRITE(out);
219 break;
220 case eHTML:
221 case eXHTML:
222 CParent::PrintChildren(out, mode);
223 break;
224 }
225 return out;
226 }
227
228
229 // plain text node
230
CHTMLPlainText(EEncodeMode encode_mode,const string & text)231 CHTMLPlainText::CHTMLPlainText(EEncodeMode encode_mode, const string& text) :
232 CNCBINode(s_GenerateNodeInternalName("plaintext", text)),
233 m_Text(text), m_EncodeMode(encode_mode)
234 {
235 }
236
CHTMLPlainText(const char * text,bool noEncode)237 CHTMLPlainText::CHTMLPlainText(const char* text, bool noEncode)
238 : CNCBINode(s_GenerateNodeInternalName("plaintext", text)),
239 m_Text(text)
240 {
241 SetNoEncode(noEncode);
242 }
243
CHTMLPlainText(const string & text,bool noEncode)244 CHTMLPlainText::CHTMLPlainText(const string& text, bool noEncode)
245 : CNCBINode(s_GenerateNodeInternalName("plaintext", text)),
246 m_Text(text)
247 {
248 SetNoEncode(noEncode);
249 }
250
~CHTMLPlainText(void)251 CHTMLPlainText::~CHTMLPlainText(void)
252 {
253 }
254
255
PrintBegin(CNcbiOstream & out,TMode mode)256 CNcbiOstream& CHTMLPlainText::PrintBegin(CNcbiOstream& out, TMode mode)
257 {
258 string str(GetText());
259 switch (mode) {
260 case ePlainText:
261 if (m_EncodeMode == eJSONEncode)
262 str = NStr::JsonEncode(str);
263 break;
264 case eHTML:
265 case eXHTML:
266 switch (m_EncodeMode) {
267 case eJSONEncode:
268 str = NStr::JsonEncode(str);
269 case eNoEncode:
270 break;
271 case eHTMLEncode:
272 str = CHTMLHelper::HTMLEncode(str);
273 }
274 break;
275 }
276 INIT_STREAM_WRITE;
277 out << str;
278 CHECK_STREAM_WRITE(out);
279 return out;
280 }
281
282
283 // text node
284
CHTMLText(const string & text,TFlags flags)285 CHTMLText::CHTMLText(const string& text, TFlags flags)
286 : CParent(s_GenerateNodeInternalName("htmltext", text)),
287 m_Text(text), m_Flags(flags)
288 {
289 return;
290 }
291
CHTMLText(const char * text,TFlags flags)292 CHTMLText::CHTMLText(const char* text, TFlags flags)
293 : CParent(s_GenerateNodeInternalName("htmltext", text)),
294 m_Text(text), m_Flags(flags)
295 {
296 return;
297 }
298
~CHTMLText(void)299 CHTMLText::~CHTMLText(void)
300 {
301 return;
302 }
303
PrintString(CNcbiOstream & out,TMode mode,const string & s) const304 CNcbiOstream& CHTMLText::PrintString(CNcbiOstream& out, TMode mode,
305 const string& s) const
306 {
307 TFlags flags = 0;
308 switch (mode) {
309 case ePlainText:
310 if ( m_Flags & fStripTextMode )
311 flags |= fStrip;
312 if ( m_Flags & fEncodeTextMode )
313 flags |= fEncode;
314 break;
315 case eHTML:
316 case eXHTML:
317 if ( m_Flags & fStripHtmlMode )
318 flags |= fStrip;
319 if ( m_Flags & fEncodeHtmlMode )
320 flags |= fEncode;
321 break;
322 }
323 string str;
324 const string *pstr = &str;
325 switch (flags) {
326 case fStrip:
327 str = CHTMLHelper::StripHTML(s);
328 break;
329 case fEncode:
330 str = CHTMLHelper::HTMLEncode(s);
331 break;
332 case fStrip | fEncode:
333 str = CHTMLHelper::HTMLEncode(CHTMLHelper::StripHTML(s));
334 break;
335 default:
336 pstr = &s;
337 }
338 INIT_STREAM_WRITE;
339 out.write(pstr->data(), pstr->size());
340 CHECK_STREAM_WRITE(out);
341 return out;
342 }
343
344
345 #define PRINT_TMP_STR \
346 if ( enable_buffering ) { \
347 pstr->write(tmp.data(), tmp.size()); \
348 } else { \
349 PrintString(out, mode, tmp); \
350 }
351
PrintBegin(CNcbiOstream & out,TMode mode)352 CNcbiOstream& CHTMLText::PrintBegin(CNcbiOstream& out, TMode mode)
353 {
354 const string& text = GetText();
355 SIZE_TYPE tagStart = s_Find(text, kTagStart);
356 if ( tagStart == NPOS ) {
357 return PrintString(out, mode, text);
358 }
359
360 // Check flag to enabe output buffering
361 bool enable_buffering = !(m_Flags & fDisableBuffering);
362 CNcbiOstrstream *pstr = 0;
363 if ( enable_buffering ) {
364 pstr = new CNcbiOstrstream;
365 }
366
367 // Printout string before the first start mapping tag
368 string tmp = text.substr(0, tagStart);
369 PRINT_TMP_STR;
370
371 // Map all tags
372 SIZE_TYPE last = tagStart;
373 do {
374 SIZE_TYPE tagNameStart = tagStart + kTagStartLen;
375 SIZE_TYPE tagNameEnd = s_Find(text, kTagEnd, tagNameStart);
376 if ( tagNameEnd == NPOS ) {
377 // tag not closed
378 NCBI_THROW(CHTMLException, eTextUnclosedTag, "tag not closed");
379 }
380 else {
381 // tag found
382 if ( last != tagStart ) {
383 tmp = text.substr(last, tagStart - last);
384 PRINT_TMP_STR;
385 }
386 string name = text.substr(tagNameStart,tagNameEnd-tagNameStart);
387 // Resolve and repeat tag
388 for (;;) {
389 CNodeRef tag = MapTagAll(name, mode);
390 if ( tag ) {
391 if ( enable_buffering ) {
392 tag->Print(*pstr, mode);
393 } else {
394 tag->Print(out, mode);
395 }
396 if ( tag->NeedRepeatTag() ) {
397 RepeatTag(false);
398 continue;
399 }
400 }
401 break;
402 }
403 last = tagNameEnd + kTagStartLen;
404 tagStart = s_Find(text, kTagStart, last);
405 }
406 } while ( tagStart != NPOS );
407
408 if ( last != text.size() ) {
409 tmp = text.substr(last);
410 PRINT_TMP_STR;
411 }
412 if ( enable_buffering ) {
413 PrintString(out, mode, CNcbiOstrstreamToString(*pstr));
414 delete pstr;
415 }
416 return out;
417 }
418
419
~CHTMLOpenElement(void)420 CHTMLOpenElement::~CHTMLOpenElement(void)
421 {
422 return;
423 }
424
x_PrintBegin(CNcbiOstream & out,TMode mode)425 CNcbiOstream& CHTMLOpenElement::x_PrintBegin(CNcbiOstream& out, TMode mode)
426 {
427 switch (mode) {
428 case ePlainText:
429 break;
430 case eHTML:
431 case eXHTML:
432 out << '<' << m_Name;
433 if ( HaveAttributes() ) {
434 for ( TAttributes::const_iterator i = Attributes().begin();
435 i != Attributes().end(); ++i ) {
436 INIT_STREAM_WRITE;
437 out << ' ' << i->first;
438 CHECK_STREAM_WRITE(out);
439
440 if ( (mode == eXHTML) ||
441 !i->second.IsOptional() ||
442 !i->second.GetValue().empty() ) {
443 string attr = i->second.GetValue();
444 out << "=\"";
445 if ( attr.empty() ) {
446 // For XHTML attribute minimization is forbidden
447 if ((mode == eXHTML) && i->second.IsOptional()) {
448 out << i->first;
449 }
450 } else {
451 if ( attr.find_first_of("\"&") != NPOS ) {
452 // Escape attributes
453 attr = CHTMLHelper::HTMLAttributeEncode(attr,
454 CHTMLHelper::fSkipEntities |
455 /* NOTE:
456 temporary use fCheckPreencoded flag here to clean up redundant
457 HTMLEncode() calls from NCBI code.
458 */
459 CHTMLHelper::fCheckPreencoded);
460 }
461 // Check tags inside attribute value
462 if (s_Find(attr, kTagStart) == NPOS) {
463 out << attr;
464 } else {
465 CHTMLText tmp(attr);
466 tmp.Print(out, mode);
467 }
468 }
469 out << '"';
470 }
471 }
472 }
473 break;
474 }
475 return out;
476 }
477
478
PrintBegin(CNcbiOstream & out,TMode mode)479 CNcbiOstream& CHTMLOpenElement::PrintBegin(CNcbiOstream& out, TMode mode)
480 {
481 x_PrintBegin(out, mode);
482 switch (mode) {
483 case ePlainText:
484 break;
485 case eHTML:
486 case eXHTML:
487 INIT_STREAM_WRITE;
488 out << '>';
489 CHECK_STREAM_WRITE(out);
490 break;
491 }
492 return out;
493 }
494
495
~CHTMLSingleElement(void)496 CHTMLSingleElement::~CHTMLSingleElement(void)
497 {
498 return;
499 }
500
501
PrintBegin(CNcbiOstream & out,TMode mode)502 CNcbiOstream& CHTMLSingleElement::PrintBegin(CNcbiOstream& out, TMode mode)
503 {
504 switch (mode) {
505 case ePlainText:
506 case eHTML:
507 CParent::PrintBegin(out, mode);
508 break;
509 case eXHTML:
510 x_PrintBegin(out, mode);
511 INIT_STREAM_WRITE;
512 out << " />";
513 CHECK_STREAM_WRITE(out);
514 break;
515 }
516 return out;
517 }
518
519
~CHTMLInlineElement(void)520 CHTMLInlineElement::~CHTMLInlineElement(void)
521 {
522 return;
523 }
524
525
PrintEnd(CNcbiOstream & out,TMode mode)526 CNcbiOstream& CHTMLInlineElement::PrintEnd(CNcbiOstream& out, TMode mode)
527 {
528 switch (mode) {
529 case ePlainText:
530 break;
531 case eHTML:
532 case eXHTML:
533 INIT_STREAM_WRITE;
534 out << "</" << m_Name << '>';
535 CHECK_STREAM_WRITE(out);
536 break;
537 }
538 return out;
539 }
540
541
~CHTMLElement(void)542 CHTMLElement::~CHTMLElement(void)
543 {
544 return;
545 }
546
547
PrintEnd(CNcbiOstream & out,TMode mode)548 CNcbiOstream& CHTMLElement::PrintEnd(CNcbiOstream& out, TMode mode)
549 {
550 CParent::PrintEnd(out, mode);
551 switch (mode) {
552 case ePlainText:
553 break;
554 case eHTML:
555 case eXHTML:
556 const TMode* previous = mode.GetPreviousContext();
557 INIT_STREAM_WRITE;
558 if ( previous ) {
559 CNCBINode* parent = previous->GetNode();
560 if ( parent && parent->HaveChildren() &&
561 parent->Children().size() > 1 )
562 // separate child nodes by newline
563 out << CHTMLHelper::GetNL();
564 } else {
565 out << CHTMLHelper::GetNL();
566 }
567 CHECK_STREAM_WRITE(out);
568 break;
569 }
570 return out;
571 }
572
573
~CHTMLBlockElement(void)574 CHTMLBlockElement::~CHTMLBlockElement(void)
575 {
576 return;
577 }
578
579
PrintEnd(CNcbiOstream & out,TMode mode)580 CNcbiOstream& CHTMLBlockElement::PrintEnd(CNcbiOstream& out, TMode mode)
581 {
582 CParent::PrintEnd(out, mode);
583 switch (mode) {
584 case ePlainText:
585 {{
586 // Add a newline iff no node on the path to the last descendant
587 // is also a block element. We only need one break.
588 CNCBINode* node = this;
589 while (node->HaveChildren()) {
590 node = node->Children().back();
591 if (dynamic_cast<CHTMLBlockElement*>(node)) {
592 return out;
593 }
594 }
595 INIT_STREAM_WRITE;
596 out << CHTMLHelper::GetNL();
597 CHECK_STREAM_WRITE(out);
598 }}
599 break;
600 case eHTML:
601 case eXHTML:
602 break;
603 }
604 return out;
605 }
606
607
608 // HTML comment.
609
610 const char CHTMLComment::sm_TagName[] = "comment";
611
~CHTMLComment(void)612 CHTMLComment::~CHTMLComment(void)
613 {
614 return;
615 }
616
Print(CNcbiOstream & out,TMode mode)617 CNcbiOstream& CHTMLComment::Print(CNcbiOstream& out, TMode mode)
618 {
619 switch (mode) {
620 case ePlainText:
621 break;
622 case eHTML:
623 case eXHTML:
624 CParent::Print(out, mode);
625 break;
626 }
627 return out;
628 }
629
PrintBegin(CNcbiOstream & out,TMode mode)630 CNcbiOstream& CHTMLComment::PrintBegin(CNcbiOstream& out, TMode mode)
631 {
632 switch (mode) {
633 case ePlainText:
634 break;
635 case eHTML:
636 case eXHTML:
637 INIT_STREAM_WRITE;
638 out << "<!--";
639 CHECK_STREAM_WRITE(out);
640 break;
641 }
642 return out;
643 }
644
PrintEnd(CNcbiOstream & out,TMode mode)645 CNcbiOstream& CHTMLComment::PrintEnd(CNcbiOstream& out, TMode mode)
646 {
647 switch (mode) {
648 case ePlainText:
649 break;
650 case eHTML:
651 case eXHTML:
652 INIT_STREAM_WRITE;
653 out << "-->";
654 CHECK_STREAM_WRITE(out);
655 break;
656 }
657 return out;
658 }
659
~CHTMLListElement(void)660 CHTMLListElement::~CHTMLListElement(void)
661 {
662 return;
663 }
664
SetType(const char * type)665 CHTMLListElement* CHTMLListElement::SetType(const char* type)
666 {
667 SetAttribute("type", type);
668 return this;
669 }
670
SetType(const string & type)671 CHTMLListElement* CHTMLListElement::SetType(const string& type)
672 {
673 SetAttribute("type", type);
674 return this;
675 }
676
SetCompact(void)677 CHTMLListElement* CHTMLListElement::SetCompact(void)
678 {
679 SetAttribute("compact");
680 return this;
681 }
682
PrintChildren(CNcbiOstream & out,TMode mode)683 CNcbiOstream& CHTMLListElement::PrintChildren(CNcbiOstream& out, TMode mode)
684 {
685 switch (mode) {
686 case ePlainText:
687 {{
688 CIndentingOstream out2(out);
689 CHTMLElement::PrintChildren(out2, mode);
690 }}
691 break;
692 case eHTML:
693 case eXHTML:
694 CHTMLElement::PrintChildren(out, mode);
695 break;
696 }
697 return out;
698 }
699
700
701 // Special char.
702
CHTMLSpecialChar(const char * html,const char * plain,int count)703 CHTMLSpecialChar::CHTMLSpecialChar(const char* html, const char* plain,
704 int count)
705 : CParent("", plain)
706 {
707 m_Name = s_GenerateNodeInternalName("specialchar", html);
708 m_Html = html;
709 m_Count = count;
710 }
711
712
~CHTMLSpecialChar(void)713 CHTMLSpecialChar::~CHTMLSpecialChar(void)
714 {
715 return;
716 }
717
718
PrintChildren(CNcbiOstream & out,TMode mode)719 CNcbiOstream& CHTMLSpecialChar::PrintChildren(CNcbiOstream& out, TMode mode)
720 {
721 switch (mode) {
722 case ePlainText:
723 for ( int i = 0; i < m_Count; i++ ) {
724 INIT_STREAM_WRITE;
725 out << m_Plain;
726 CHECK_STREAM_WRITE(out);
727 }
728 break;
729 case eHTML:
730 case eXHTML:
731 for ( int i = 0; i < m_Count; i++ ) {
732 INIT_STREAM_WRITE;
733 out << "&" << m_Html << ";";
734 CHECK_STREAM_WRITE(out);
735 }
736 break;
737 }
738 return out;
739 }
740
741
742 // <html> tag.
743
744 const char CHTML_html::sm_TagName[] = "html";
745
~CHTML_html(void)746 CHTML_html::~CHTML_html(void)
747 {
748 return;
749 }
750
Init(void)751 void CHTML_html::Init(void)
752 {
753 return;
754 }
755
CHTML_tr(void)756 CHTML_tr::CHTML_tr(void)
757 : CParent("tr"), m_Parent(0)
758 {
759 return;
760 }
761
CHTML_tr(CNCBINode * node)762 CHTML_tr::CHTML_tr(CNCBINode* node)
763 : CParent("tr", node), m_Parent(0)
764 {
765 return;
766 }
767
CHTML_tr(const string & text)768 CHTML_tr::CHTML_tr(const string& text)
769 : CParent("tr", text), m_Parent(0)
770 {
771 return;
772 }
773
DoAppendChild(CNCBINode * node)774 void CHTML_tr::DoAppendChild(CNCBINode* node)
775 {
776 CHTML_tc* cell = dynamic_cast<CHTML_tc*>(node);
777 if ( cell ) {
778 // Adding new cell
779 _ASSERT(!cell->m_Parent);
780 ResetTableCache();
781 cell->m_Parent = this;
782 }
783 CParent::DoAppendChild(node);
784 }
785
AppendCell(CHTML_tc * cell)786 void CHTML_tr::AppendCell(CHTML_tc* cell)
787 {
788 _ASSERT(!cell->m_Parent);
789 cell->m_Parent = this;
790 CParent::DoAppendChild(cell);
791 }
792
ResetTableCache(void)793 void CHTML_tr::ResetTableCache(void)
794 {
795 if ( m_Parent )
796 m_Parent->ResetTableCache();
797 }
798
PrintEnd(CNcbiOstream & out,TMode mode)799 CNcbiOstream& CHTML_tr::PrintEnd(CNcbiOstream& out, TMode mode)
800 {
801 CParent::PrintEnd(out, mode);
802 switch (mode) {
803 case ePlainText:
804 if ( m_Parent ) {
805 INIT_STREAM_WRITE;
806 out << CHTMLHelper::GetNL();
807 if (m_Parent->m_IsRowSep == CHTML_table::ePrintRowSep) {
808 out << string(GetTextLength(mode), m_Parent->m_RowSepChar)
809 << CHTMLHelper::GetNL();
810 }
811 CHECK_STREAM_WRITE(out);
812 }
813 break;
814 case eHTML:
815 case eXHTML:
816 break;
817 }
818 return out;
819 }
820
PrintChildren(CNcbiOstream & out,TMode mode)821 CNcbiOstream& CHTML_tr::PrintChildren(CNcbiOstream& out, TMode mode)
822 {
823 if ( !HaveChildren() ) {
824 return out;
825 }
826 switch (mode) {
827 case ePlainText:
828 break;
829 case eHTML:
830 case eXHTML:
831 return CParent::PrintChildren(out, mode);
832 }
833 out << m_Parent->m_ColSepL;
834 NON_CONST_ITERATE ( TChildren, i, Children() ) {
835 if ( i != Children().begin() ) {
836 INIT_STREAM_WRITE;
837 out << m_Parent->m_ColSepM;
838 CHECK_STREAM_WRITE(out);
839 }
840 Node(i)->Print(out, mode);
841 }
842 INIT_STREAM_WRITE;
843 out << m_Parent->m_ColSepR;
844 CHECK_STREAM_WRITE(out);
845
846 return out;
847 }
848
GetTextLength(TMode mode)849 SIZE_TYPE CHTML_tr::GetTextLength(TMode mode)
850 {
851 if ( !HaveChildren() ) {
852 return 0;
853 }
854 CNcbiOstrstream sout;
855 SIZE_TYPE cols = 0;
856
857 NON_CONST_ITERATE ( TChildren, i, Children() ) {
858 Node(i)->Print(sout, mode);
859 cols++;
860 }
861 SIZE_TYPE textlen = (SIZE_TYPE)GetOssSize(sout);
862
863 switch (mode) {
864 case ePlainText:
865 textlen += m_Parent->m_ColSepL.length() +
866 m_Parent->m_ColSepR.length();
867 if ( cols ) {
868 textlen += m_Parent->m_ColSepM.length() * (cols - 1);
869 }
870 break;
871 case eHTML:
872 case eXHTML:
873 break;
874 }
875 return textlen;
876 }
877
~CHTML_tc(void)878 CHTML_tc::~CHTML_tc(void)
879 {
880 return;
881 }
882
SetRowSpan(TIndex span)883 CHTML_tc* CHTML_tc::SetRowSpan(TIndex span)
884 {
885 SetAttribute("rowspan", span);
886 return this;
887 }
888
SetColSpan(TIndex span)889 CHTML_tc* CHTML_tc::SetColSpan(TIndex span)
890 {
891 SetAttribute("colspan", span);
892 return this;
893 }
894
895 static
x_GetSpan(const CHTML_tc * node,const string & attributeName)896 CHTML_table::TIndex x_GetSpan(const CHTML_tc* node,
897 const string& attributeName)
898 {
899 if ( !node->HaveAttribute(attributeName) ) {
900 return 1;
901 }
902 const string& value = node->GetAttribute(attributeName);
903
904 try {
905 CHTML_table::TIndex span = NStr::StringToUInt(value);
906 if ( span > 0 ) {
907 return span;
908 }
909 }
910 catch ( exception& ) {
911 // Error will be posted later
912 }
913 ERR_POST_X(1, "Bad attribute: " << attributeName << "=\"" << value << "\"");
914 return 1;
915 }
916
DoSetAttribute(const string & name,const string & value,bool optional)917 void CHTML_tc::DoSetAttribute(const string& name,
918 const string& value, bool optional)
919 {
920 if (name == "rowspan" || name == "colspan") {
921 // Changing cell size
922 ResetTableCache();
923 }
924 CParent::DoSetAttribute(name, value, optional);
925 }
926
ResetTableCache(void)927 void CHTML_tc::ResetTableCache(void)
928 {
929 if ( m_Parent ) {
930 m_Parent->ResetTableCache();
931 }
932 }
933
SetUsed()934 void CHTML_tc_Cache::SetUsed()
935 {
936 if ( IsUsed() ) {
937 NCBI_THROW(CHTMLException, eTableCellUse, "overlapped table cells");
938 }
939 m_Used = true;
940 }
941
SetCellNode(CHTML_tc * cellNode)942 void CHTML_tc_Cache::SetCellNode(CHTML_tc* cellNode)
943 {
944 SetUsed();
945 m_Node = cellNode;
946 }
947
948 static
x_NextSize(CHTML_table::TIndex size,CHTML_table::TIndex limit)949 CHTML_table::TIndex x_NextSize(CHTML_table::TIndex size,
950 CHTML_table::TIndex limit)
951 {
952 do {
953 if ( size == 0 )
954 size = 2;
955 else
956 size *= 2;
957 } while ( size < limit );
958 return size;
959 }
960
GetCellCache(TIndex col)961 CHTML_tc_Cache& CHTML_tr_Cache::GetCellCache(TIndex col)
962 {
963 TIndex count = GetCellCount();
964 if ( col >= count ) {
965 TIndex newCount = col + 1;
966 TIndex size = m_CellsSize;
967 if ( newCount > size ) {
968 TIndex newSize = x_NextSize(size, newCount);
969 CHTML_tc_Cache* newCells = new CHTML_tc_Cache[newSize];
970 for ( TIndex i = 0; i < count; ++i )
971 newCells[i] = m_Cells[i];
972 delete[] m_Cells;
973 m_Cells = newCells;
974 m_CellsSize = newSize;
975 }
976 m_CellCount = newCount;
977 }
978 return m_Cells[col];
979 }
980
SetUsedCells(TIndex colBegin,TIndex colEnd)981 void CHTML_tr_Cache::SetUsedCells(TIndex colBegin, TIndex colEnd)
982 {
983 for ( TIndex col = colBegin; col < colEnd; ++col ) {
984 GetCellCache(col).SetUsed();
985 }
986 }
987
AppendCell(CHTML_tr * rowNode,TIndex col,CHTML_tc * cellNode,TIndex colSpan)988 void CHTML_tr_Cache::AppendCell(CHTML_tr* rowNode, TIndex col,
989 CHTML_tc* cellNode, TIndex colSpan)
990 {
991 _ASSERT(m_FilledCellCount <= col);
992 for ( TIndex i = m_FilledCellCount; i < col; ++i ) {
993 CHTML_tc_Cache& cellCache = GetCellCache(i);
994 if ( !cellCache.IsUsed() ) {
995 CHTML_tc* cell;
996 cell = new CHTML_td;
997 rowNode->AppendCell(cell);
998 cellCache.SetCellNode(cell);
999 }
1000 }
1001 CHTML_tc_Cache& cellCache = GetCellCache(col);
1002 _ASSERT(!cellCache.IsUsed());
1003 _ASSERT(x_GetSpan(cellNode, "colspan") == colSpan);
1004 rowNode->AppendCell(cellNode);
1005 cellCache.SetCellNode(cellNode);
1006 if ( colSpan != 1 ) {
1007 SetUsedCells(col + 1, col + colSpan);
1008 }
1009 m_FilledCellCount = col + colSpan;
1010 }
1011
SetUsedCells(CHTML_tc * cellNode,TIndex colBegin,TIndex colEnd)1012 void CHTML_tr_Cache::SetUsedCells(CHTML_tc* cellNode,
1013 TIndex colBegin, TIndex colEnd)
1014 {
1015 GetCellCache(colBegin).SetCellNode(cellNode);
1016 SetUsedCells(colBegin + 1, colEnd);
1017 m_FilledCellCount = colEnd;
1018 }
1019
1020
~CHTML_table_Cache(void)1021 CHTML_table_Cache::~CHTML_table_Cache(void)
1022 {
1023 for ( TIndex i = 0; i < GetRowCount(); ++i ) {
1024 delete m_Rows[i];
1025 }
1026 delete[] m_Rows;
1027 }
1028
1029
GetRowCache(TIndex row)1030 CHTML_tr_Cache& CHTML_table_Cache::GetRowCache(TIndex row)
1031 {
1032 TIndex count = GetRowCount();
1033 if ( row >= count ) {
1034 TIndex newCount = row + 1;
1035 TIndex size = m_RowsSize;
1036 if ( newCount > size ) {
1037 TIndex newSize = x_NextSize(size, newCount);
1038 CHTML_tr_Cache** newRows = new CHTML_tr_Cache*[newSize];
1039 for ( TIndex i = 0; i < count; ++i )
1040 newRows[i] = m_Rows[i];
1041 delete[] m_Rows;
1042 m_Rows = newRows;
1043 m_RowsSize = newSize;
1044 }
1045 for ( TIndex i = count; i < newCount; ++i )
1046 m_Rows[i] = new CHTML_tr_Cache;
1047 m_RowCount = newCount;
1048 }
1049 return *m_Rows[row];
1050 }
1051
InitRow(TIndex row,CHTML_tr * rowNode)1052 void CHTML_table_Cache::InitRow(TIndex row, CHTML_tr* rowNode)
1053 {
1054 CHTML_tr_Cache& rowCache = GetRowCache(row);
1055 m_Rows[row]->SetRowNode(rowNode);
1056 m_FilledRowCount = row + 1;
1057
1058 // Scan all children (which should be <TH> or <TD> tags)
1059 if ( rowNode->HaveChildren() ) {
1060 // Beginning with column 0
1061 TIndex col = 0;
1062 for ( CNCBINode::TChildren::iterator iCol = rowNode->ChildBegin(),
1063 iColEnd = rowNode->ChildEnd();
1064 iCol != iColEnd; ++iCol ) {
1065 CHTML_tc* cellNode =
1066 dynamic_cast<CHTML_tc*>(rowNode->Node(iCol));
1067
1068 if ( !cellNode ) {
1069 continue;
1070 }
1071
1072 // Skip all used cells
1073 while ( rowCache.GetCellCache(col).IsUsed() ) {
1074 ++col;
1075 }
1076
1077 // Determine current cell size
1078 TIndex rowSpan = x_GetSpan(cellNode, "rowspan");
1079 TIndex colSpan = x_GetSpan(cellNode, "colspan");
1080
1081 // End of new cell in columns
1082 rowCache.SetUsedCells(cellNode, col, col + colSpan);
1083 if ( rowSpan > 1 ) {
1084 SetUsedCells(row + 1, row + rowSpan, col, col + colSpan);
1085 }
1086
1087 // Skip this cell's columns
1088 col += colSpan;
1089 }
1090 }
1091 }
1092
CHTML_table_Cache(CHTML_table * table)1093 CHTML_table_Cache::CHTML_table_Cache(CHTML_table* table)
1094 : m_Node(table),
1095 m_RowCount(0), m_RowsSize(0), m_Rows(0), m_FilledRowCount(0)
1096 {
1097 // Scan all children (which should be <TR> tags)
1098 if ( table->HaveChildren() ) {
1099 // Beginning with row 0
1100 TIndex row = 0;
1101 for ( CNCBINode::TChildren::iterator iRow = table->ChildBegin(),
1102 iRowEnd = table->ChildEnd(); iRow != iRowEnd; ++iRow ) {
1103 CHTML_tr* rowNode = dynamic_cast<CHTML_tr*>(table->Node(iRow));
1104 if ( !rowNode ) {
1105 continue;
1106 }
1107 InitRow(row, rowNode);
1108 ++row;
1109 }
1110 }
1111 }
1112
GetRowNode(TIndex row)1113 CHTML_tr* CHTML_table_Cache::GetRowNode(TIndex row)
1114 {
1115 GetRowCache(row);
1116 while ( row >= m_FilledRowCount ) {
1117 CHTML_tr* rowNode = new CHTML_tr;
1118 m_Node->AppendRow(rowNode);
1119 m_Rows[m_FilledRowCount++]->SetRowNode(rowNode);
1120 }
1121 return m_Rows[row]->GetRowNode();
1122 }
1123
SetUsedCells(TIndex rowBegin,TIndex rowEnd,TIndex colBegin,TIndex colEnd)1124 void CHTML_table_Cache::SetUsedCells(TIndex rowBegin, TIndex rowEnd,
1125 TIndex colBegin, TIndex colEnd)
1126 {
1127 for ( TIndex row = rowBegin; row < rowEnd; ++row ) {
1128 GetRowCache(row).SetUsedCells(colBegin, colEnd);
1129 }
1130 }
1131
GetCellNode(TIndex row,TIndex col,CHTML_table::ECellType type)1132 CHTML_tc* CHTML_table_Cache::GetCellNode(TIndex row, TIndex col,
1133 CHTML_table::ECellType type)
1134 {
1135 CHTML_tr_Cache& rowCache = GetRowCache(row);
1136 if ( col < rowCache.GetCellCount() ) {
1137 CHTML_tc_Cache& cellCache = rowCache.GetCellCache(col);
1138 if ( cellCache.IsNode() ) {
1139 CHTML_tc* cell = cellCache.GetCellNode();
1140 switch ( type ) {
1141 case CHTML_table::eHeaderCell:
1142 if ( !dynamic_cast<CHTML_th*>(cell) )
1143 NCBI_THROW(CHTMLException, eTableCellType,
1144 "wrong cell type: TH expected");
1145 break;
1146 case CHTML_table::eDataCell:
1147 if ( !dynamic_cast<CHTML_td*>(cell) )
1148 NCBI_THROW(CHTMLException, eTableCellType,
1149 "wrong cell type: TD expected");
1150 break;
1151 default:
1152 break;
1153 }
1154 return cell;
1155 }
1156 if ( cellCache.IsUsed() )
1157 NCBI_THROW(CHTMLException, eTableCellUse,
1158 "invalid use of big table cell");
1159 }
1160 CHTML_tc* cell;
1161 if ( type == CHTML_table::eHeaderCell ) {
1162 cell = new CHTML_th;
1163 } else {
1164 cell = new CHTML_td;
1165 }
1166 rowCache.AppendCell(GetRowNode(row), col, cell, 1);
1167 return cell;
1168 }
1169
GetCellNode(TIndex row,TIndex col,CHTML_table::ECellType type,TIndex rowSpan,TIndex colSpan)1170 CHTML_tc* CHTML_table_Cache::GetCellNode(TIndex row, TIndex col,
1171 CHTML_table::ECellType type,
1172 TIndex rowSpan, TIndex colSpan)
1173 {
1174 CHTML_tr_Cache& rowCache = GetRowCache(row);
1175 if ( col < rowCache.GetCellCount() ) {
1176 CHTML_tc_Cache& cellCache = rowCache.GetCellCache(col);
1177 if ( cellCache.IsNode() ) {
1178 CHTML_tc* cell = cellCache.GetCellNode();
1179 switch ( type ) {
1180 case CHTML_table::eHeaderCell:
1181 if ( !dynamic_cast<CHTML_th*>(cell) )
1182 NCBI_THROW(CHTMLException, eTableCellType,
1183 "wrong cell type: TH expected");
1184 break;
1185 case CHTML_table::eDataCell:
1186 if ( !dynamic_cast<CHTML_td*>(cell) )
1187 NCBI_THROW(CHTMLException, eTableCellType,
1188 "wrong cell type: TD expected");
1189 break;
1190 default:
1191 break;
1192 }
1193 if ( x_GetSpan(cell, "rowspan") != rowSpan ||
1194 x_GetSpan(cell, "colspan") != colSpan )
1195 NCBI_THROW(CHTMLException, eTableCellUse,
1196 "cannot change table cell size");
1197 return cell;
1198 }
1199 if ( cellCache.IsUsed() )
1200 NCBI_THROW(CHTMLException, eTableCellUse,
1201 "invalid use of big table cell");
1202 }
1203
1204 CHTML_tc* cell;
1205 if ( type == CHTML_table::eHeaderCell ) {
1206 cell = new CHTML_th;
1207 } else {
1208 cell = new CHTML_td;
1209 }
1210 if ( colSpan != 1 ) {
1211 cell->SetColSpan(colSpan);
1212 }
1213 if ( rowSpan != 1 ) {
1214 cell->SetRowSpan(rowSpan);
1215 }
1216 rowCache.AppendCell(GetRowNode(row), col, cell, colSpan);
1217 if ( rowSpan != 1 ) {
1218 SetUsedCells(row + 1, row + rowSpan, col, col + colSpan);
1219 }
1220 return cell;
1221 }
1222
CHTML_table(void)1223 CHTML_table::CHTML_table(void)
1224 : CParent("table"),
1225 m_CurrentRow(TIndex(-1)), m_CurrentCol(TIndex(-1)),
1226 m_ColSepL(kEmptyStr), m_ColSepM(" "), m_ColSepR(kEmptyStr),
1227 m_RowSepChar('-'), m_IsRowSep(eSkipRowSep)
1228 {
1229 return;
1230 }
1231
~CHTML_table(void)1232 CHTML_table::~CHTML_table(void)
1233 {
1234 return;
1235 }
1236
GetCache(void) const1237 CHTML_table_Cache& CHTML_table::GetCache(void) const
1238 {
1239 CHTML_table_Cache* cache = m_Cache.get();
1240 if ( !cache ) {
1241 m_Cache.reset(cache =
1242 new CHTML_table_Cache(const_cast<CHTML_table*>(this)));
1243 }
1244 return *cache;
1245 }
1246
DoAppendChild(CNCBINode * node)1247 void CHTML_table::DoAppendChild(CNCBINode* node)
1248 {
1249 CHTML_tr* row = dynamic_cast<CHTML_tr*>(node);
1250 if ( row ) {
1251 // Adding new row
1252 _ASSERT(!row->m_Parent);
1253 ResetTableCache();
1254 row->m_Parent = this;
1255 }
1256 CParent::DoAppendChild(node);
1257 }
1258
AppendRow(CHTML_tr * row)1259 void CHTML_table::AppendRow(CHTML_tr* row)
1260 {
1261 _ASSERT(!row->m_Parent);
1262 row->m_Parent = this;
1263 CParent::DoAppendChild(row);
1264 }
1265
Row(TIndex row)1266 CHTML_tr* CHTML_table::Row(TIndex row)
1267 {
1268 return GetCache().GetRowNode(row);
1269 }
1270
Cell(TIndex row,TIndex col,ECellType type)1271 CHTML_tc* CHTML_table::Cell(TIndex row, TIndex col, ECellType type)
1272 {
1273 m_CurrentRow = (row == TIndex(-1)) ? 0 : row;
1274 m_CurrentCol = (col == TIndex(-1)) ? 0 : col;
1275 return GetCache().GetCellNode(m_CurrentRow, m_CurrentCol, type);
1276 }
1277
Cell(TIndex row,TIndex col,ECellType type,TIndex rowSpan,TIndex colSpan)1278 CHTML_tc* CHTML_table::Cell(TIndex row, TIndex col, ECellType type,
1279 TIndex rowSpan, TIndex colSpan)
1280 {
1281 m_CurrentRow = (row == TIndex(-1)) ? 0 : row;
1282 m_CurrentCol = (col == TIndex(-1)) ? 0 : col;
1283 return GetCache().GetCellNode(m_CurrentRow, m_CurrentCol,
1284 type, rowSpan, colSpan);
1285 }
1286
CheckTable(void) const1287 void CHTML_table::CheckTable(void) const
1288 {
1289 GetCache();
1290 }
1291
CalculateNumberOfColumns(void) const1292 CHTML_table::TIndex CHTML_table::CalculateNumberOfColumns(void) const
1293 {
1294 CHTML_table_Cache& cache = GetCache();
1295 TIndex columns = 0;
1296 for ( TIndex i = 0; i < cache.GetRowCount(); ++i ) {
1297 columns = max(columns, cache.GetRowCache(i).GetCellCount());
1298 }
1299 return columns;
1300 }
1301
CalculateNumberOfRows(void) const1302 CHTML_table::TIndex CHTML_table::CalculateNumberOfRows(void) const
1303 {
1304 return GetCache().GetRowCount();
1305 }
1306
PrintBegin(CNcbiOstream & out,TMode mode)1307 CNcbiOstream& CHTML_table::PrintBegin(CNcbiOstream& out, TMode mode)
1308 {
1309 switch (mode) {
1310 case ePlainText:
1311 INIT_STREAM_WRITE;
1312 out << CHTMLHelper::GetNL();
1313 CHECK_STREAM_WRITE(out);
1314 if ( m_IsRowSep == ePrintRowSep ) {
1315 SIZE_TYPE seplen = 0;
1316 // Find length of first non-empty row
1317 NON_CONST_ITERATE ( TChildren, i, Children() ) {
1318 if ( (seplen =
1319 dynamic_cast<CHTML_tr*>(&**i)->GetTextLength(mode)) >0) {
1320 break;
1321 }
1322 }
1323 if ( !seplen ) {
1324 seplen = 1;
1325 }
1326 INIT_STREAM_WRITE;
1327 out << string(seplen, m_RowSepChar) << CHTMLHelper::GetNL();
1328 CHECK_STREAM_WRITE(out);
1329 }
1330 break;
1331 case eHTML:
1332 case eXHTML:
1333 // Set column widths.
1334 if ( HaveChildren() ) {
1335 ITERATE ( TColWidths, w, m_ColWidths ) {
1336 // Scan all children (which should be <TR> tags)
1337 // Beginning with row 0
1338 TIndex row = 0;
1339 for ( CNCBINode::TChildren::iterator iRow = ChildBegin(),
1340 iRowEnd = ChildEnd(); iRow != iRowEnd; ++iRow ) {
1341 try {
1342 CHTML_tc* cell = Cell(row, (TIndex)w->first);
1343 if ( cell ) {
1344 cell->SetWidth(w->second);
1345 }
1346 }
1347 catch (CHTMLException&) {
1348 // catch exception with messages about absent cells
1349 }
1350 ++row;
1351 }
1352 }
1353 }
1354 break;
1355 }
1356 return CParent::PrintBegin(out, mode);
1357 }
1358
SetPlainSeparators(const string & col_left,const string & col_middle,const string & col_right,const char row_sep_char,ERowPlainSep is_row_sep)1359 void CHTML_table::SetPlainSeparators(const string& col_left,
1360 const string& col_middle,
1361 const string& col_right,
1362 const char row_sep_char,
1363 ERowPlainSep is_row_sep)
1364 {
1365 m_ColSepL = col_left;
1366 m_ColSepM = col_middle;
1367 m_ColSepR = col_right;
1368 m_RowSepChar = row_sep_char;
1369 m_IsRowSep = is_row_sep;
1370 }
1371
1372
1373 // <form> tag.
1374
CHTML_form(void)1375 CHTML_form::CHTML_form(void)
1376 : CParent("form")
1377 {
1378 return;
1379 }
1380
CHTML_form(const string & url,EMethod method)1381 CHTML_form::CHTML_form(const string& url, EMethod method)
1382 : CParent("form")
1383 {
1384 Init(url, method);
1385 }
1386
CHTML_form(const string & url,CNCBINode * node,EMethod method)1387 CHTML_form::CHTML_form(const string& url, CNCBINode* node, EMethod method)
1388 : CParent("form", node)
1389 {
1390 Init(url, method);
1391 }
1392
~CHTML_form(void)1393 CHTML_form::~CHTML_form(void)
1394 {
1395 return;
1396 }
1397
Init(const string & url,EMethod method)1398 void CHTML_form::Init(const string& url, EMethod method)
1399 {
1400 SetOptionalAttribute("action", url);
1401 switch ( method ) {
1402 case eGet:
1403 SetAttribute("method", "GET");
1404 break;
1405 case ePost:
1406 SetAttribute("enctype",
1407 "application/x-www-form-urlencoded");
1408 SetAttribute("method", "POST");
1409 break;
1410 case ePostData:
1411 SetAttribute("enctype",
1412 "multipart/form-data");
1413 SetAttribute("method", "POST");
1414 break;
1415 }
1416 }
1417
AddHidden(const string & name,const string & value)1418 void CHTML_form::AddHidden(const string& name, const string& value)
1419 {
1420 AppendChild(new CHTML_hidden(name, value));
1421 }
1422
AddHidden(const string & name,int value)1423 void CHTML_form::AddHidden(const string& name, int value)
1424 {
1425 AppendChild(new CHTML_hidden(name, value));
1426 }
1427
1428
1429 // <input> tag.
1430
CHTML_input(const char * type,const string & name)1431 CHTML_input::CHTML_input(const char* type, const string& name)
1432 : CParent("input")
1433 {
1434 SetAttribute("type", type);
1435 if ( !name.empty() ) {
1436 SetNameAttribute(name);
1437 }
1438 }
1439
~CHTML_input(void)1440 CHTML_input::~CHTML_input(void)
1441 {
1442 return;
1443 }
1444
1445
1446 // <legend> tag.
1447
CHTML_legend(const string & legend)1448 CHTML_legend::CHTML_legend(const string& legend)
1449 : CParent("legend", legend)
1450 {
1451 return;
1452 }
1453
CHTML_legend(CHTMLNode * legend)1454 CHTML_legend::CHTML_legend(CHTMLNode* legend)
1455 : CParent("legend", legend)
1456 {
1457 return;
1458 }
1459
~CHTML_legend(void)1460 CHTML_legend::~CHTML_legend(void)
1461 {
1462 return;
1463 }
1464
1465 // <fieldset> tag.
1466
CHTML_fieldset(void)1467 CHTML_fieldset::CHTML_fieldset(void)
1468 : CParent("fieldset")
1469 {
1470 return;
1471 }
1472
CHTML_fieldset(const string & legend)1473 CHTML_fieldset::CHTML_fieldset(const string& legend)
1474 : CParent("fieldset", new CHTML_legend(legend))
1475 {
1476 return;
1477 }
1478
CHTML_fieldset(CHTML_legend * legend)1479 CHTML_fieldset::CHTML_fieldset(CHTML_legend* legend)
1480 : CParent("fieldset", legend)
1481 {
1482 return;
1483 }
1484
~CHTML_fieldset(void)1485 CHTML_fieldset::~CHTML_fieldset(void)
1486 {
1487 return;
1488 }
1489
1490
1491 // <label> tag.
1492
CHTML_label(const string & text)1493 CHTML_label::CHTML_label(const string& text)
1494 : CParent("label", text)
1495 {
1496 return;
1497 }
1498
CHTML_label(const string & text,const string & idRef)1499 CHTML_label::CHTML_label(const string& text, const string& idRef)
1500 : CParent("label", text)
1501 {
1502 SetFor(idRef);
1503 }
1504
~CHTML_label(void)1505 CHTML_label::~CHTML_label(void)
1506 {
1507 return;
1508 }
1509
SetFor(const string & idRef)1510 void CHTML_label::SetFor(const string& idRef)
1511 {
1512 SetAttribute("for", idRef);
1513 }
1514
1515
1516 // <textarea> tag.
1517
CHTML_textarea(const string & name,int cols,int rows)1518 CHTML_textarea::CHTML_textarea(const string& name, int cols, int rows)
1519 : CParent("textarea")
1520 {
1521 if ( !name.empty() ) {
1522 SetNameAttribute(name);
1523 }
1524 SetAttribute("cols", cols);
1525 SetAttribute("rows", rows);
1526 }
1527
CHTML_textarea(const string & name,int cols,int rows,const string & value)1528 CHTML_textarea::CHTML_textarea(const string& name, int cols, int rows,
1529 const string& value)
1530 : CParent("textarea", value)
1531 {
1532 SetNameAttribute(name);
1533 SetAttribute("cols", cols);
1534 SetAttribute("rows", rows);
1535 }
1536
~CHTML_textarea(void)1537 CHTML_textarea::~CHTML_textarea(void)
1538 {
1539 return;
1540 }
1541
1542
1543 // <input type=checkbox> tag.
1544
1545 const char CHTML_checkbox::sm_InputType[] = "checkbox";
1546
CHTML_checkbox(const string & name)1547 CHTML_checkbox::CHTML_checkbox(const string& name)
1548 : CParent(sm_InputType, name)
1549 {
1550 return;
1551 }
1552
CHTML_checkbox(const string & name,const string & value)1553 CHTML_checkbox::CHTML_checkbox(const string& name, const string& value)
1554 : CParent(sm_InputType, name)
1555 {
1556 SetOptionalAttribute("value", value);
1557 }
1558
CHTML_checkbox(const string & name,bool checked,const string & description)1559 CHTML_checkbox::CHTML_checkbox(const string& name, bool checked,
1560 const string& description)
1561 : CParent(sm_InputType, name)
1562 {
1563 SetOptionalAttribute("checked", checked);
1564 // Add the description at the end
1565 AppendPlainText(description);
1566 }
1567
CHTML_checkbox(const string & name,const string & value,bool checked,const string & description)1568 CHTML_checkbox::CHTML_checkbox(const string& name, const string& value,
1569 bool checked, const string& description)
1570 : CParent(sm_InputType, name)
1571 {
1572 SetOptionalAttribute("value", value);
1573 SetOptionalAttribute("checked", checked);
1574 // Add the description at the end
1575 AppendPlainText(description);
1576 }
1577
~CHTML_checkbox(void)1578 CHTML_checkbox::~CHTML_checkbox(void)
1579 {
1580 return;
1581 }
1582
1583
1584 // <input type=image> tag.
1585
1586 const char CHTML_image::sm_InputType[] = "image";
1587
CHTML_image(const string & name,const string & src,const string & alt)1588 CHTML_image::CHTML_image(const string& name, const string& src,
1589 const string& alt)
1590 : CParent(sm_InputType, name)
1591 {
1592 SetAttribute("src", src);
1593 SetOptionalAttribute("alt", alt);
1594 }
1595
CHTML_image(const string & name,const string & src,int border,const string & alt)1596 CHTML_image::CHTML_image(const string& name, const string& src, int border,
1597 const string& alt)
1598 : CParent(sm_InputType, name)
1599 {
1600 SetAttribute("src", src);
1601 SetAttribute("border", border);
1602 SetOptionalAttribute("alt", alt);
1603 }
1604
~CHTML_image(void)1605 CHTML_image::~CHTML_image(void)
1606 {
1607 return;
1608 }
1609
1610
1611 // <input type=radio> tag.
1612
1613 const char CHTML_radio::sm_InputType[] = "radio";
1614
CHTML_radio(const string & name,const string & value)1615 CHTML_radio::CHTML_radio(const string& name, const string& value)
1616 : CParent(sm_InputType, name)
1617 {
1618 SetAttribute("value", value);
1619 }
1620
CHTML_radio(const string & name,const string & value,bool checked,const string & description)1621 CHTML_radio::CHTML_radio(const string& name, const string& value,
1622 bool checked, const string& description)
1623 : CParent(sm_InputType, name)
1624 {
1625 SetAttribute("value", value);
1626 SetOptionalAttribute("checked", checked);
1627 AppendPlainText(description); // adds the description at the end
1628 }
1629
~CHTML_radio(void)1630 CHTML_radio::~CHTML_radio(void)
1631 {
1632 return;
1633 }
1634
1635
1636 // <input type=hidden> tag.
1637
1638 const char CHTML_hidden::sm_InputType[] = "hidden";
1639
CHTML_hidden(const string & name,const string & value)1640 CHTML_hidden::CHTML_hidden(const string& name, const string& value)
1641 : CParent(sm_InputType, name)
1642 {
1643 SetAttribute("value", value);
1644 }
1645
CHTML_hidden(const string & name,int value)1646 CHTML_hidden::CHTML_hidden(const string& name, int value)
1647 : CParent(sm_InputType, name)
1648 {
1649 SetAttribute("value", value);
1650 }
1651
~CHTML_hidden(void)1652 CHTML_hidden::~CHTML_hidden(void)
1653 {
1654 return;
1655 }
1656
1657
1658 // <input type=password> tag.
1659
1660 const char CHTML_password::sm_InputType[] = "password";
1661
CHTML_password(const string & name,const string & value)1662 CHTML_password::CHTML_password(const string& name, const string& value)
1663 : CParent(sm_InputType, name)
1664 {
1665 SetOptionalAttribute("value", value);
1666 }
1667
CHTML_password(const string & name,int size,const string & value)1668 CHTML_password::CHTML_password(const string& name, int size,
1669 const string& value)
1670 : CParent(sm_InputType, name)
1671 {
1672 SetSize(size);
1673 SetOptionalAttribute("value", value);
1674 }
1675
CHTML_password(const string & name,int size,int maxlength,const string & value)1676 CHTML_password::CHTML_password(const string& name, int size, int maxlength,
1677 const string& value)
1678 : CParent(sm_InputType, name)
1679 {
1680 SetSize(size);
1681 SetAttribute("maxlength", maxlength);
1682 SetOptionalAttribute("value", value);
1683 }
1684
~CHTML_password(void)1685 CHTML_password::~CHTML_password(void)
1686 {
1687 return;
1688 }
1689
1690
1691 // <input type=submit> tag.
1692
1693 const char CHTML_submit::sm_InputType[] = "submit";
1694
CHTML_submit(const string & label)1695 CHTML_submit::CHTML_submit(const string& label)
1696 : CParent(sm_InputType, NcbiEmptyString)
1697 {
1698 SetOptionalAttribute("value", label);
1699 }
1700
CHTML_submit(const string & name,const string & label)1701 CHTML_submit::CHTML_submit(const string& name, const string& label)
1702 : CParent(sm_InputType, name)
1703 {
1704 SetOptionalAttribute("value", label);
1705 }
1706
~CHTML_submit(void)1707 CHTML_submit::~CHTML_submit(void)
1708 {
1709 return;
1710 }
1711
1712
1713 // <input type=reset> tag.
1714
1715 const char CHTML_reset::sm_InputType[] = "reset";
1716
CHTML_reset(const string & label)1717 CHTML_reset::CHTML_reset(const string& label)
1718 : CParent(sm_InputType, NcbiEmptyString)
1719 {
1720 SetOptionalAttribute("value", label);
1721 }
1722
~CHTML_reset(void)1723 CHTML_reset::~CHTML_reset(void)
1724 {
1725 return;
1726 }
1727
1728
1729 // <input type=button> tag
1730
1731 const char CHTML_input_button::sm_InputType[] = "button";
1732
CHTML_input_button(const string & label)1733 CHTML_input_button::CHTML_input_button(const string& label)
1734 : CParent(sm_InputType, NcbiEmptyString)
1735 {
1736 SetOptionalAttribute("value", label);
1737 }
1738
CHTML_input_button(const string & name,const string & label)1739 CHTML_input_button::CHTML_input_button(const string& name, const string& label)
1740 : CParent(sm_InputType, name)
1741 {
1742 SetOptionalAttribute("value", label);
1743 }
1744
~CHTML_input_button(void)1745 CHTML_input_button::~CHTML_input_button(void)
1746 {
1747 return;
1748 }
1749
1750
1751 // <input type=text> tag.
1752
1753 const char CHTML_text::sm_InputType[] = "text";
1754
CHTML_text(const string & name,const string & value)1755 CHTML_text::CHTML_text(const string& name, const string& value)
1756 : CParent(sm_InputType, name)
1757 {
1758 SetOptionalAttribute("value", value);
1759 }
1760
CHTML_text(const string & name,int size,const string & value)1761 CHTML_text::CHTML_text(const string& name, int size, const string& value)
1762 : CParent(sm_InputType, name)
1763 {
1764 SetSize(size);
1765 SetOptionalAttribute("value", value);
1766 }
1767
CHTML_text(const string & name,int size,int maxlength,const string & value)1768 CHTML_text::CHTML_text(const string& name, int size, int maxlength,
1769 const string& value)
1770 : CParent(sm_InputType, name)
1771 {
1772 SetSize(size);
1773 SetAttribute("maxlength", maxlength);
1774 SetOptionalAttribute("value", value);
1775 }
1776
~CHTML_text(void)1777 CHTML_text::~CHTML_text(void)
1778 {
1779 return;
1780 }
1781
1782
1783 // <input type=file> tag.
1784
1785 const char CHTML_file::sm_InputType[] = "file";
1786
CHTML_file(const string & name,const string & value)1787 CHTML_file::CHTML_file(const string& name, const string& value)
1788 : CParent(sm_InputType, name)
1789 {
1790 SetOptionalAttribute("value", value);
1791 }
1792
~CHTML_file(void)1793 CHTML_file::~CHTML_file(void)
1794 {
1795 return;
1796 }
1797
1798
1799 // <button> tag
1800
1801 const char CHTML_button::sm_TagName[] = "button";
1802
CHTML_button(const string & text,EButtonType type,const string & name,const string & value)1803 CHTML_button::CHTML_button(const string& text, EButtonType type,
1804 const string& name, const string& value)
1805 : CParent(sm_TagName, text)
1806 {
1807 SetType(type);
1808 SetSubmitData(name, value);
1809 }
1810
CHTML_button(CNCBINode * contents,EButtonType type,const string & name,const string & value)1811 CHTML_button::CHTML_button(CNCBINode* contents, EButtonType type,
1812 const string& name, const string& value)
1813 : CParent(sm_TagName, contents)
1814 {
1815 SetType(type);
1816 SetSubmitData(name, value);
1817 }
1818
SetType(EButtonType type)1819 CHTML_button* CHTML_button::SetType(EButtonType type)
1820 {
1821 switch ( type ) {
1822 case eSubmit:
1823 SetAttribute("type", "submit");
1824 break;
1825 case eReset:
1826 SetAttribute("type", "reset");
1827 break;
1828 case eButton:
1829 SetAttribute("type", "button");
1830 break;
1831 }
1832 return this;
1833 }
1834
SetSubmitData(const string & name,const string & value)1835 CHTML_button* CHTML_button::SetSubmitData(const string& name,
1836 const string& value)
1837 {
1838 SetOptionalAttribute("name", name);
1839 SetOptionalAttribute("value", value);
1840 return this;
1841 }
1842
~CHTML_button(void)1843 CHTML_button::~CHTML_button(void)
1844 {
1845 return;
1846 }
1847
1848
1849 // <select> tag.
1850
1851 const char CHTML_select::sm_TagName[] = "select";
1852
~CHTML_select(void)1853 CHTML_select::~CHTML_select(void)
1854 {
1855 return;
1856 }
1857
1858
1859 // <optgroup> tag.
1860
1861 const char CHTML_optgroup::sm_TagName[] = "optgroup";
1862
~CHTML_optgroup(void)1863 CHTML_optgroup::~CHTML_optgroup(void)
1864 {
1865 return;
1866 }
1867
1868
1869 // <option> tag.
1870
1871 const char CHTML_option::sm_TagName[] = "option";
1872
~CHTML_option(void)1873 CHTML_option::~CHTML_option(void)
1874 {
1875 return;
1876 }
1877
1878
1879 // <a> tag.
1880
1881 const char CHTML_a::sm_TagName[] = "a";
1882
~CHTML_a(void)1883 CHTML_a::~CHTML_a(void)
1884 {
1885 return;
1886 }
1887
1888
1889 // <br> tag.
1890
1891 const char CHTML_br::sm_TagName[] = "br";
1892
CHTML_br(int count)1893 CHTML_br::CHTML_br(int count)
1894 : CParent(sm_TagName)
1895 {
1896 for ( int i = 1; i < count; ++i ) {
1897 AppendChild(new CHTML_br());
1898 }
1899 }
1900
~CHTML_br(void)1901 CHTML_br::~CHTML_br(void)
1902 {
1903 return;
1904 }
1905
PrintBegin(CNcbiOstream & out,TMode mode)1906 CNcbiOstream& CHTML_br::PrintBegin(CNcbiOstream& out, TMode mode)
1907 {
1908 switch (mode) {
1909 case ePlainText:
1910 INIT_STREAM_WRITE;
1911 out << CHTMLHelper::GetNL();
1912 CHECK_STREAM_WRITE(out);
1913 break;
1914 case eHTML:
1915 case eXHTML:
1916 CParent::PrintBegin(out, mode);
1917 break;
1918 }
1919 return out;
1920 }
1921
1922
1923 // <img> tag.
1924
CHTML_img(const string & url,const string & alt)1925 CHTML_img::CHTML_img(const string& url, const string& alt)
1926 : CParent("img")
1927 {
1928 SetAttribute("src", url);
1929 SetOptionalAttribute("alt", alt);
1930 }
1931
CHTML_img(const string & url,int width,int height,const string & alt)1932 CHTML_img::CHTML_img(const string& url, int width, int height,
1933 const string& alt)
1934 : CParent("img")
1935 {
1936 SetAttribute("src", url);
1937 SetOptionalAttribute("alt", alt);
1938 SetWidth(width);
1939 SetHeight(height);
1940 }
1941
~CHTML_img(void)1942 CHTML_img::~CHTML_img(void)
1943 {
1944 return;
1945 }
1946
UseMap(const string & mapname)1947 void CHTML_img::UseMap(const string& mapname)
1948 {
1949 if ( mapname.find("#") == NPOS ) {
1950 SetAttribute("usemap", "#" + mapname);
1951 } else {
1952 SetAttribute("usemap", mapname);
1953 }
1954 }
1955
UseMap(const CHTML_map * const mapnode)1956 void CHTML_img::UseMap(const CHTML_map* const mapnode)
1957 {
1958 UseMap(mapnode->GetNameAttribute());
1959 }
1960
1961
1962
1963 // <map> tag.
1964
CHTML_map(const string & name)1965 CHTML_map::CHTML_map(const string& name)
1966 : CParent("map")
1967 {
1968 SetNameAttribute(name);
1969 }
1970
~CHTML_map(void)1971 CHTML_map::~CHTML_map(void)
1972 {
1973 return;
1974 }
1975
1976
1977 // <area> tag.
1978
1979 const char CHTML_area::sm_TagName[] = "area";
1980
~CHTML_area(void)1981 CHTML_area::~CHTML_area(void)
1982 {
1983 return;
1984 }
1985
DefineRect(int x1,int y1,int x2,int y2)1986 CHTML_area* CHTML_area::DefineRect(int x1, int y1, int x2, int y2)
1987 {
1988 vector<string> c;
1989 c.push_back(NStr::IntToString(x1));
1990 c.push_back(NStr::IntToString(y1));
1991 c.push_back(NStr::IntToString(x2));
1992 c.push_back(NStr::IntToString(y2));
1993 SetAttribute("shape", "rect");
1994 SetAttribute("coords", NStr::Join(c, ","));
1995 return this;
1996 }
1997
DefineCircle(int x,int y,int radius)1998 CHTML_area* CHTML_area::DefineCircle(int x, int y, int radius)
1999 {
2000 vector<string> c;
2001 c.push_back(NStr::IntToString(x));
2002 c.push_back(NStr::IntToString(y));
2003 c.push_back(NStr::IntToString(radius));
2004 SetAttribute("shape", "circle");
2005 SetAttribute("coords", NStr::Join(c, ","));
2006 return this;
2007 }
2008
DefinePolygon(int coords[],int count)2009 CHTML_area* CHTML_area::DefinePolygon(int coords[], int count)
2010 {
2011 string c;
2012 for(int i = 0; i<count; i++) {
2013 if ( i ) {
2014 c += ",";
2015 }
2016 c += NStr::IntToString(coords[i]);
2017 }
2018 SetAttribute("shape", "poly");
2019 SetAttribute("coords", c);
2020 return this;
2021 }
2022
DefinePolygon(vector<int> coords)2023 CHTML_area* CHTML_area::DefinePolygon(vector<int> coords)
2024 {
2025 string c;
2026 ITERATE(vector<int>, it, coords) {
2027 if ( it != coords.begin() ) {
2028 c += ",";
2029 }
2030 c += NStr::IntToString(*it);
2031 }
2032 SetAttribute("shape", "poly");
2033 SetAttribute("coords", c);
2034 return this;
2035 }
2036
DefinePolygon(list<int> coords)2037 CHTML_area* CHTML_area::DefinePolygon(list<int> coords)
2038 {
2039 string c;
2040 ITERATE(list<int>, it, coords) {
2041 if ( it != coords.begin() ) {
2042 c += ",";
2043 }
2044 c += NStr::IntToString(*it);
2045 }
2046 SetAttribute("shape", "poly");
2047 SetAttribute("coords", c);
2048 return this;
2049 }
2050
2051
2052 // <dl> tag.
2053
2054 const char CHTML_dl::sm_TagName[] = "dl";
2055
~CHTML_dl(void)2056 CHTML_dl::~CHTML_dl(void)
2057 {
2058 return;
2059 }
2060
AppendTerm(const string & term,const string & definition)2061 CHTML_dl* CHTML_dl::AppendTerm(const string& term, const string& definition)
2062 {
2063 AppendChild(new CHTML_dt(term));
2064 if ( !definition.empty() )
2065 AppendChild(new CHTML_dd(definition));
2066 return this;
2067 }
2068
AppendTerm(const string & term,CNCBINode * definition)2069 CHTML_dl* CHTML_dl::AppendTerm(const string& term, CNCBINode* definition)
2070 {
2071 AppendChild(new CHTML_dt(term));
2072 if ( definition )
2073 AppendChild(new CHTML_dd(definition));
2074 return this;
2075 }
2076
AppendTerm(CNCBINode * term,const string & definition)2077 CHTML_dl* CHTML_dl::AppendTerm(CNCBINode* term, const string& definition)
2078 {
2079 AppendChild(new CHTML_dt(term));
2080 if ( !definition.empty() ) {
2081 AppendChild(new CHTML_dd(definition));
2082 }
2083 return this;
2084 }
2085
AppendTerm(CNCBINode * term,CNCBINode * definition)2086 CHTML_dl* CHTML_dl::AppendTerm(CNCBINode* term, CNCBINode* definition)
2087 {
2088 AppendChild(new CHTML_dt(term));
2089 if ( definition )
2090 AppendChild(new CHTML_dd(definition));
2091 return this;
2092 }
2093
SetCompact(void)2094 CHTML_dl* CHTML_dl::SetCompact(void)
2095 {
2096 SetAttribute("compact");
2097 return this;
2098 }
2099
2100
2101 // <ol> tag.
2102
2103 const char CHTML_ol::sm_TagName[] = "ol";
2104
~CHTML_ol(void)2105 CHTML_ol::~CHTML_ol(void)
2106 {
2107 }
2108
SetStart(int start)2109 CHTML_ol* CHTML_ol::SetStart(int start)
2110 {
2111 SetAttribute("start", start);
2112 return this;
2113 }
2114
2115
2116 // <ul> tag.
2117
2118 const char CHTML_ul::sm_TagName[] = "ul";
2119
~CHTML_ul(void)2120 CHTML_ul::~CHTML_ul(void)
2121 {
2122 return;
2123 }
2124
2125
2126 // <dir> tag.
2127
2128 const char CHTML_dir::sm_TagName[] = "dir";
2129
~CHTML_dir(void)2130 CHTML_dir::~CHTML_dir(void)
2131 {
2132 return;
2133 }
2134
2135
2136 // <menu> tag.
2137
2138 const char CHTML_menu::sm_TagName[] = "menu";
2139
~CHTML_menu(void)2140 CHTML_menu::~CHTML_menu(void)
2141 {
2142 return;
2143 }
2144
2145 const char CHTML_font::sm_TagName[] = "font";
2146
~CHTML_font(void)2147 CHTML_font::~CHTML_font(void)
2148 {
2149 return;
2150 }
2151
2152
2153 // <font> tag.
2154
SetTypeFace(const string & typeface)2155 CHTML_font* CHTML_font::SetTypeFace(const string& typeface)
2156 {
2157 SetAttribute("face", typeface);
2158 return this;
2159 }
2160
SetRelativeSize(int size)2161 CHTML_font* CHTML_font::SetRelativeSize(int size)
2162 {
2163 if ( size != 0 )
2164 SetAttribute("size", NStr::IntToString(size, NStr::fWithSign));
2165 return this;
2166 }
2167
2168 const char CHTML_basefont::sm_TagName[] = "basefont";
2169
~CHTML_basefont(void)2170 CHTML_basefont::~CHTML_basefont(void)
2171 {
2172 return;
2173 }
2174
SetTypeFace(const string & typeface)2175 CHTML_basefont* CHTML_basefont::SetTypeFace(const string& typeface)
2176 {
2177 SetAttribute("typeface", typeface);
2178 return this;
2179 }
2180
~CHTML_color(void)2181 CHTML_color::~CHTML_color(void)
2182 {
2183 return;
2184 }
2185
2186
2187 // <hr> tag.
2188
2189 const char CHTML_hr::sm_TagName[] = "hr";
2190
~CHTML_hr(void)2191 CHTML_hr::~CHTML_hr(void)
2192 {
2193 return;
2194 }
2195
SetNoShade(void)2196 CHTML_hr* CHTML_hr::SetNoShade(void)
2197 {
2198 SetAttribute("noshade");
2199 return this;
2200 }
2201
PrintBegin(CNcbiOstream & out,TMode mode)2202 CNcbiOstream& CHTML_hr::PrintBegin(CNcbiOstream& out, TMode mode)
2203 {
2204 switch (mode) {
2205 case ePlainText:
2206 INIT_STREAM_WRITE;
2207 out << CHTMLHelper::GetNL() << CHTMLHelper::GetNL();
2208 CHECK_STREAM_WRITE(out);
2209 break;
2210 case eHTML:
2211 case eXHTML:
2212 CParent::PrintBegin(out, mode);
2213 break;
2214 }
2215 return out;
2216 }
2217
2218
2219 // <meta> tag.
2220
2221 const char CHTML_meta::sm_TagName[] = "meta";
2222
CHTML_meta(EType mtype,const string & var,const string & content)2223 CHTML_meta::CHTML_meta(EType mtype, const string& var, const string& content)
2224 : CParent(sm_TagName)
2225 {
2226 SetAttribute(( mtype == eName ) ? "name" : "http-equiv", var);
2227 SetAttribute("content", content);
2228 }
2229
2230
~CHTML_meta(void)2231 CHTML_meta::~CHTML_meta(void)
2232 {
2233 return;
2234 }
2235
2236
2237 // <script> tag.
2238
2239 const char CHTML_script::sm_TagName[] = "script";
2240
CHTML_script(const string & stype)2241 CHTML_script::CHTML_script(const string& stype)
2242 : CParent(sm_TagName)
2243 {
2244 SetAttribute("type", stype);
2245 }
2246
2247
CHTML_script(const string & stype,const string & url)2248 CHTML_script::CHTML_script(const string& stype, const string& url)
2249 : CParent(sm_TagName)
2250 {
2251 SetAttribute("type", stype);
2252 SetAttribute("src", url);
2253 }
2254
2255
~CHTML_script(void)2256 CHTML_script::~CHTML_script(void)
2257 {
2258 return;
2259 }
2260
AppendScript(const string & script)2261 CHTML_script* CHTML_script::AppendScript(const string& script)
2262 {
2263 const string& nl = CHTMLHelper::GetNL();
2264 AppendChild(
2265 new CHTMLPlainText(nl + "<!--" + nl + script + "-->" + nl, true));
2266 return this;
2267 }
2268
2269
2270 // Other tags.
2271
2272 #define DEFINE_HTML_ELEMENT(Tag) \
2273 CHTML_NAME(Tag)::~CHTML_NAME(Tag)(void) \
2274 { \
2275 } \
2276 const char CHTML_NAME(Tag)::sm_TagName[] = #Tag
2277
2278
2279 DEFINE_HTML_ELEMENT(head);
2280 DEFINE_HTML_ELEMENT(body);
2281 DEFINE_HTML_ELEMENT(base);
2282 DEFINE_HTML_ELEMENT(isindex);
2283 DEFINE_HTML_ELEMENT(link);
2284 DEFINE_HTML_ELEMENT(noscript);
2285 DEFINE_HTML_ELEMENT(object);
2286 DEFINE_HTML_ELEMENT(style);
2287 DEFINE_HTML_ELEMENT(title);
2288 DEFINE_HTML_ELEMENT(address);
2289 DEFINE_HTML_ELEMENT(blockquote);
2290 DEFINE_HTML_ELEMENT(center);
2291 DEFINE_HTML_ELEMENT(div);
2292 DEFINE_HTML_ELEMENT(h1);
2293 DEFINE_HTML_ELEMENT(h2);
2294 DEFINE_HTML_ELEMENT(h3);
2295 DEFINE_HTML_ELEMENT(h4);
2296 DEFINE_HTML_ELEMENT(h5);
2297 DEFINE_HTML_ELEMENT(h6);
2298 DEFINE_HTML_ELEMENT(p);
2299 DEFINE_HTML_ELEMENT(pre);
2300 DEFINE_HTML_ELEMENT(dt);
2301 DEFINE_HTML_ELEMENT(dd);
2302 DEFINE_HTML_ELEMENT(li);
2303 DEFINE_HTML_ELEMENT(caption);
2304 DEFINE_HTML_ELEMENT(col);
2305 DEFINE_HTML_ELEMENT(colgroup);
2306 DEFINE_HTML_ELEMENT(thead);
2307 DEFINE_HTML_ELEMENT(tbody);
2308 DEFINE_HTML_ELEMENT(tfoot);
2309 DEFINE_HTML_ELEMENT(th);
2310 DEFINE_HTML_ELEMENT(td);
2311 DEFINE_HTML_ELEMENT(applet);
2312 DEFINE_HTML_ELEMENT(param);
2313 DEFINE_HTML_ELEMENT(cite);
2314 DEFINE_HTML_ELEMENT(code);
2315 DEFINE_HTML_ELEMENT(dfn);
2316 DEFINE_HTML_ELEMENT(em);
2317 DEFINE_HTML_ELEMENT(kbd);
2318 DEFINE_HTML_ELEMENT(samp);
2319 DEFINE_HTML_ELEMENT(strike);
2320 DEFINE_HTML_ELEMENT(strong);
2321 DEFINE_HTML_ELEMENT(var);
2322 DEFINE_HTML_ELEMENT(b);
2323 DEFINE_HTML_ELEMENT(big);
2324 DEFINE_HTML_ELEMENT(i);
2325 DEFINE_HTML_ELEMENT(s);
2326 DEFINE_HTML_ELEMENT(small);
2327 DEFINE_HTML_ELEMENT(sub);
2328 DEFINE_HTML_ELEMENT(sup);
2329 DEFINE_HTML_ELEMENT(tt);
2330 DEFINE_HTML_ELEMENT(u);
2331 DEFINE_HTML_ELEMENT(blink);
2332 DEFINE_HTML_ELEMENT(span);
2333
2334
2335 END_NCBI_SCOPE
2336