System.Web.UI.WebControls.IDataBoundItemControl from reference source
[mono.git] / mcs / class / System.Web / System.Web.UI / HtmlTextWriter.cs
1 // 
2 // System.Web.UI.HtmlTextWriter
3 //
4 // Author:
5 //        Ben Maurer <bmaurer@novell.com>
6 //
7 // (c) 2005-2010 Novell, Inc (http://novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.IO;
30 using System.Globalization;
31 using System.Collections;
32 using System.Security.Permissions;
33 using System.Text;
34 using System.Web.UI.WebControls;
35
36 namespace System.Web.UI {
37
38         // CAS
39         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
41         public class HtmlTextWriter : TextWriter {
42
43
44                 readonly static Hashtable _tagTable;
45                 readonly static Hashtable _attributeTable;
46                 readonly static Hashtable _styleTable;
47
48                 static HtmlTextWriter ()
49                 {
50                         _tagTable = new Hashtable (tags.Length, StringComparer.OrdinalIgnoreCase);
51                         _attributeTable = new Hashtable (htmlattrs.Length, StringComparer.OrdinalIgnoreCase);
52                         _styleTable = new Hashtable (htmlstyles.Length, StringComparer.OrdinalIgnoreCase);
53                         foreach (HtmlTag tag in tags)
54                                 _tagTable.Add (tag.name, tag);
55
56                         foreach (HtmlAttribute attr in htmlattrs)
57                                 _attributeTable.Add (attr.name, attr);
58
59                         foreach (HtmlStyle style in htmlstyles)
60                                 _styleTable.Add (style.name, style);
61                 }
62
63                 public HtmlTextWriter (TextWriter writer) : this (writer, DefaultTabString)
64                 {
65                 }
66
67                 public HtmlTextWriter (TextWriter writer, string tabString)
68                 {
69                         b = writer;
70                         tab_string = tabString;
71                 }
72
73                 internal static string StaticGetStyleName (System.Web.UI.HtmlTextWriterStyle styleKey)
74                 {
75                         if ((int) styleKey < htmlstyles.Length)
76                                 return htmlstyles [(int) styleKey].name;
77
78                         return null;
79                 }
80
81                 [MonoTODO ("Does nothing")]
82                 protected static void RegisterAttribute (string name, HtmlTextWriterAttribute key)
83                 {
84                 }
85
86                 [MonoTODO ("Does nothing")]
87                 protected static void RegisterStyle (string name, HtmlTextWriterStyle key)
88                 {
89                 }
90
91                 [MonoTODO ("Does nothing")]
92                 protected static void RegisterTag (string name, HtmlTextWriterTag key)
93                 {
94                 }
95
96
97                 public virtual void AddAttribute (HtmlTextWriterAttribute key, string value, bool fEncode)
98                 {
99                         if (fEncode)
100                                 value = HttpUtility.HtmlAttributeEncode (value);
101
102                         AddAttribute (GetAttributeName (key), value, key);
103                 }
104
105
106                 public virtual void AddAttribute (HtmlTextWriterAttribute key, string value)
107                 {
108                         if ((key != HtmlTextWriterAttribute.Name) && (key != HtmlTextWriterAttribute.Id))
109                                 value = HttpUtility.HtmlAttributeEncode (value);
110
111                         AddAttribute (GetAttributeName (key), value, key);
112                 }
113
114
115                 public virtual void AddAttribute (string name, string value, bool fEncode)
116                 {
117                         if (fEncode)
118                                 value = HttpUtility.HtmlAttributeEncode (value);
119
120                         AddAttribute (name, value, GetAttributeKey (name));
121                 }
122
123                 public virtual void AddAttribute (string name, string value)
124                 {
125                         HtmlTextWriterAttribute key = GetAttributeKey (name);
126
127                         if ((key != HtmlTextWriterAttribute.Name) && (key != HtmlTextWriterAttribute.Id))
128                                 value = HttpUtility.HtmlAttributeEncode (value);
129
130                         AddAttribute (name, value, key);
131                 }
132
133                 protected virtual void AddAttribute (string name, string value, HtmlTextWriterAttribute key)
134                 {
135                         NextAttrStack ();
136                         attrs [attrs_pos].name = name;
137                         attrs [attrs_pos].value = value;
138                         attrs [attrs_pos].key = key;
139                 }
140
141
142                 protected virtual void AddStyleAttribute (string name, string value, HtmlTextWriterStyle key)
143                 {
144                         NextStyleStack ();
145                         styles [styles_pos].name = name;
146                         value = HttpUtility.HtmlAttributeEncode (value);
147                         styles [styles_pos].value = value;
148                         styles [styles_pos].key = key;
149                 }
150
151
152                 public virtual void AddStyleAttribute (string name, string value)
153                 {
154                         AddStyleAttribute (name, value, GetStyleKey (name));
155                 }
156
157                 public virtual void AddStyleAttribute (HtmlTextWriterStyle key, string value)
158                 {
159                         AddStyleAttribute (GetStyleName (key), value, key);
160                 }
161
162                 public override void Close ()
163                 {
164                         b.Close ();
165                 }
166
167                 protected virtual string EncodeAttributeValue (HtmlTextWriterAttribute attrKey, string value)
168                 {
169                         return HttpUtility.HtmlAttributeEncode (value);
170                 }
171
172                 protected string EncodeAttributeValue (string value, bool fEncode)
173                 {
174                         if (fEncode)
175                                 return HttpUtility.HtmlAttributeEncode (value);
176                         return value;
177                 }
178
179                 protected string EncodeUrl (string url)
180                 {
181                         return HttpUtility.UrlPathEncode (url);
182                 }
183
184
185                 protected virtual void FilterAttributes ()
186                 {
187                         AddedAttr style_attr = new AddedAttr ();
188
189                         for (int i = 0; i <= attrs_pos; i++) {
190                                 AddedAttr a = attrs [i];
191                                 if (OnAttributeRender (a.name, a.value, a.key)) {
192                                         if (a.key == HtmlTextWriterAttribute.Style) {
193                                                 style_attr = a;
194                                                 continue;
195                                         }
196
197                                         WriteAttribute (a.name, a.value, false);
198                                 }
199                         }
200
201                         if (styles_pos != -1 || style_attr.value != null) {
202                                 Write (SpaceChar);
203                                 Write ("style");
204                                 Write (EqualsDoubleQuoteString);
205
206
207                                 for (int i = 0; i <= styles_pos; i++) {
208                                         AddedStyle a = styles [i];
209                                         if (OnStyleAttributeRender (a.name, a.value, a.key)) {
210                                                 if (a.key == HtmlTextWriterStyle.BackgroundImage)
211                                                         a.value = String.Concat ("url(", HttpUtility.UrlPathEncode (a.value), ")");
212                                                 WriteStyleAttribute (a.name, a.value, false);
213                                         }
214                                 }
215
216                                 Write (style_attr.value);
217                                 Write (DoubleQuoteChar);
218                         }
219
220                         styles_pos = attrs_pos = -1;
221                 }
222
223                 public override void Flush ()
224                 {
225                         b.Flush ();
226                 }
227
228                 protected HtmlTextWriterAttribute GetAttributeKey (string attrName)
229                 {
230                         object attribute = _attributeTable [attrName];
231                         if (attribute == null)
232                                 return (HtmlTextWriterAttribute) (-1);
233
234                         return (HtmlTextWriterAttribute) ((HtmlAttribute) attribute).key;
235                 }
236
237                 protected string GetAttributeName (HtmlTextWriterAttribute attrKey)
238                 {
239                         if ((int) attrKey < htmlattrs.Length)
240                                 return htmlattrs [(int) attrKey].name;
241
242                         return null;
243                 }
244
245                 protected HtmlTextWriterStyle GetStyleKey (string styleName)
246                 {
247                         object style = _styleTable [styleName];
248                         if (style == null)
249                                 return (HtmlTextWriterStyle) (-1);
250
251                         return (HtmlTextWriterStyle) ((HtmlStyle) style).key;
252                 }
253
254                 protected string GetStyleName (HtmlTextWriterStyle styleKey)
255                 {
256                         return StaticGetStyleName (styleKey);
257                 }
258
259                 protected virtual HtmlTextWriterTag GetTagKey (string tagName)
260                 {
261                         object tag = _tagTable [tagName];
262                         if (tag == null)
263                                 return HtmlTextWriterTag.Unknown;
264
265                         return (HtmlTextWriterTag) ((HtmlTag) tag).key;
266                 }
267
268                 internal static string StaticGetTagName (HtmlTextWriterTag tagKey)
269                 {
270                         if ((int) tagKey < tags.Length)
271                                 return tags [(int) tagKey].name;
272
273                         return null;
274                 }
275
276
277                 protected virtual string GetTagName (HtmlTextWriterTag tagKey)
278                 {
279                         if ((int) tagKey < tags.Length)
280                                 return tags [(int) tagKey].name;
281
282                         return null;
283                 }
284
285                 protected bool IsAttributeDefined (HtmlTextWriterAttribute key)
286                 {
287                         string value;
288                         return IsAttributeDefined (key, out value);
289                 }
290
291                 protected bool IsAttributeDefined (HtmlTextWriterAttribute key, out string value)
292                 {
293                         for (int i = 0; i <= attrs_pos; i++)
294                                 if (attrs [i].key == key) {
295                                         value = attrs [i].value;
296                                         return true;
297                                 }
298
299                         value = null;
300                         return false;
301                 }
302
303                 protected bool IsStyleAttributeDefined (HtmlTextWriterStyle key)
304                 {
305                         string value;
306                         return IsStyleAttributeDefined (key, out value);
307                 }
308
309                 protected bool IsStyleAttributeDefined (HtmlTextWriterStyle key, out string value)
310                 {
311                         for (int i = 0; i <= styles_pos; i++)
312                                 if (styles [i].key == key) {
313                                         value = styles [i].value;
314                                         return true;
315                                 }
316
317                         value = null;
318                         return false;
319                 }
320
321                 protected virtual bool OnAttributeRender (string name, string value, HtmlTextWriterAttribute key)
322                 {
323                         return true;
324                 }
325
326                 protected virtual bool OnStyleAttributeRender (string name, string value, HtmlTextWriterStyle key)
327                 {
328                         return true;
329                 }
330
331                 protected virtual bool OnTagRender (string name, HtmlTextWriterTag key)
332                 {
333                         return true;
334                 }
335
336
337                 protected virtual void OutputTabs ()
338                 {
339                         if (!newline)
340                                 return;
341                         newline = false;
342
343                         for (int i = 0; i < Indent; i++)
344                                 b.Write (tab_string);
345                 }
346
347
348
349                 protected string PopEndTag ()
350                 {
351                         if (tagstack_pos == -1)
352                                 throw new InvalidOperationException ();
353
354                         string s = TagName;
355                         tagstack_pos--;
356                         return s;
357                 }
358
359                 protected void PushEndTag (string endTag)
360                 {
361                         NextTagStack ();
362                         TagName = endTag;
363                 }
364
365                 void PushEndTag (HtmlTextWriterTag t)
366                 {
367                         NextTagStack ();
368                         TagKey = t;
369                 }
370
371
372                 protected virtual string RenderAfterContent ()
373                 {
374                         return null;
375                 }
376
377                 protected virtual string RenderAfterTag ()
378                 {
379                         return null;
380                 }
381
382                 protected virtual string RenderBeforeContent ()
383                 {
384                         return null;
385                 }
386
387                 protected virtual string RenderBeforeTag ()
388                 {
389                         return null;
390                 }
391
392                 public virtual void RenderBeginTag (string tagName)
393                 {
394                         bool ignore = !OnTagRender (tagName, GetTagKey (tagName));
395
396                         PushEndTag (tagName);
397                         TagIgnore = ignore;
398                         DoBeginTag ();
399                 }
400
401                 public virtual void RenderBeginTag (HtmlTextWriterTag tagKey)
402                 {
403                         bool ignore = !OnTagRender (GetTagName (tagKey), tagKey);
404
405                         PushEndTag (tagKey);
406                         DoBeginTag ();
407                         TagIgnore = ignore;
408                 }
409
410                 void WriteIfNotNull (string s)
411                 {
412                         if (s != null)
413                                 Write (s);
414                 }
415
416
417                 void DoBeginTag ()
418                 {
419                         WriteIfNotNull (RenderBeforeTag ());
420                         if (!TagIgnore) {
421                                 WriteBeginTag (TagName);
422                                 FilterAttributes ();
423
424                                 HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
425
426                                 switch (tags [(int) key].tag_type) {
427                                         case TagType.Inline:
428                                                 Write (TagRightChar);
429                                                 break;
430                                         case TagType.Block:
431                                                 Write (TagRightChar);
432                                                 WriteLine ();
433                                                 Indent++;
434                                                 break;
435                                         case TagType.SelfClosing:
436                                                 Write (SelfClosingTagEnd);
437                                                 break;
438                                 }
439                         }
440                         
441                         // FIXME what do i do for self close here?
442                         WriteIfNotNull (RenderBeforeContent ());
443                 }
444
445
446                 public virtual void RenderEndTag ()
447                 {
448                         
449                         // FIXME what do i do for self close here?
450                         WriteIfNotNull (RenderAfterContent ());
451
452                         if (!TagIgnore) {
453                                 HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
454
455                                 switch (tags [(int) key].tag_type) {
456                                         case TagType.Inline:
457                                                 WriteEndTag (TagName);
458                                                 break;
459                                         case TagType.Block:
460                                                 Indent--;
461                                                 WriteLineNoTabs (String.Empty);
462                                                 WriteEndTag (TagName);
463
464                                                 break;
465                                         case TagType.SelfClosing:
466                                                 // NADA
467                                                 break;
468                                 }
469                         }
470                         
471                         WriteIfNotNull (RenderAfterTag ());
472
473                         PopEndTag ();
474                 }
475
476
477                 public virtual void WriteAttribute (string name, string value, bool fEncode)
478                 {
479                         Write (SpaceChar);
480                         Write (name);
481                         if (value != null) {
482                                 Write (EqualsDoubleQuoteString);
483                                 value = EncodeAttributeValue (value, fEncode);
484                                 Write (value);
485                                 Write (DoubleQuoteChar);
486                         }
487                 }
488
489
490                 public virtual void WriteBeginTag (string tagName)
491                 {
492                         Write (TagLeftChar);
493                         Write (tagName);
494                 }
495
496                 public virtual void WriteEndTag (string tagName)
497                 {
498                         Write (EndTagLeftChars);
499                         Write (tagName);
500                         Write (TagRightChar);
501                 }
502
503                 public virtual void WriteFullBeginTag (string tagName)
504                 {
505                         Write (TagLeftChar);
506                         Write (tagName);
507                         Write (TagRightChar);
508                 }
509
510                 public virtual void WriteStyleAttribute (string name, string value)
511                 {
512                         WriteStyleAttribute (name, value, false);
513                 }
514
515                 public virtual void WriteStyleAttribute (string name, string value, bool fEncode)
516                 {
517                         Write (name);
518                         Write (StyleEqualsChar);
519                         Write (EncodeAttributeValue (value, fEncode));
520                         Write (SemicolonChar);
521                 }
522
523                 public override void Write (char [] buffer, int index, int count)
524                 {
525                         OutputTabs ();
526                         b.Write (buffer, index, count);
527                 }
528
529                 public override void Write (double value)
530                 {
531                         OutputTabs ();
532                         b.Write (value);
533                 }
534
535                 public override void Write (char value)
536                 {
537                         OutputTabs ();
538                         b.Write (value);
539                 }
540
541                 public override void Write (char [] buffer)
542                 {
543                         OutputTabs ();
544                         b.Write (buffer);
545                 }
546
547                 public override void Write (int value)
548                 {
549                         OutputTabs ();
550                         b.Write (value);
551                 }
552
553                 public override void Write (string format, object arg0)
554                 {
555                         OutputTabs ();
556                         b.Write (format, arg0);
557                 }
558
559                 public override void Write (string format, object arg0, object arg1)
560                 {
561                         OutputTabs ();
562                         b.Write (format, arg0, arg1);
563                 }
564
565                 public override void Write (string format, params object [] args)
566                 {
567                         OutputTabs ();
568                         b.Write (format, args);
569                 }
570
571                 public override void Write (string s)
572                 {
573                         OutputTabs ();
574                         b.Write (s);
575                 }
576
577                 public override void Write (long value)
578                 {
579                         OutputTabs ();
580                         b.Write (value);
581                 }
582
583                 public override void Write (object value)
584                 {
585                         OutputTabs ();
586                         b.Write (value);
587                 }
588
589                 public override void Write (float value)
590                 {
591                         OutputTabs ();
592                         b.Write (value);
593                 }
594
595                 public override void Write (bool value)
596                 {
597                         OutputTabs ();
598                         b.Write (value);
599                 }
600
601                 public virtual void WriteAttribute (string name, string value)
602                 {
603                         WriteAttribute (name, value, false);
604                 }
605
606                 public override void WriteLine (char value)
607                 {
608                         OutputTabs ();
609                         b.WriteLine (value);
610                         newline = true;
611                 }
612
613                 public override void WriteLine (long value)
614                 {
615                         OutputTabs ();
616                         b.WriteLine (value);
617                         newline = true;
618                 }
619
620                 public override void WriteLine (object value)
621                 {
622                         OutputTabs ();
623                         b.WriteLine (value);
624                         newline = true;
625                 }
626
627                 public override void WriteLine (double value)
628                 {
629                         OutputTabs ();
630                         b.WriteLine (value);
631                         newline = true;
632                 }
633
634                 public override void WriteLine (char [] buffer, int index, int count)
635                 {
636                         OutputTabs ();
637                         b.WriteLine (buffer, index, count);
638                         newline = true;
639                 }
640
641                 public override void WriteLine (char [] buffer)
642                 {
643                         OutputTabs ();
644                         b.WriteLine (buffer);
645                         newline = true;
646                 }
647
648                 public override void WriteLine (bool value)
649                 {
650                         OutputTabs ();
651                         b.WriteLine (value);
652                         newline = true;
653                 }
654
655                 public override void WriteLine ()
656                 {
657                         OutputTabs ();
658                         b.WriteLine ();
659                         newline = true;
660                 }
661
662                 public override void WriteLine (int value)
663                 {
664                         OutputTabs ();
665                         b.WriteLine (value);
666                         newline = true;
667                 }
668
669                 public override void WriteLine (string format, object arg0, object arg1)
670                 {
671                         OutputTabs ();
672                         b.WriteLine (format, arg0, arg1);
673                         newline = true;
674                 }
675
676                 public override void WriteLine (string format, object arg0)
677                 {
678                         OutputTabs ();
679                         b.WriteLine (format, arg0);
680                         newline = true;
681                 }
682
683                 public override void WriteLine (string format, params object [] args)
684                 {
685                         OutputTabs ();
686                         b.WriteLine (format, args);
687                         newline = true;
688                 }
689
690                 [CLSCompliant (false)]
691                 public override void WriteLine (uint value)
692                 {
693                         OutputTabs ();
694                         b.WriteLine (value);
695                         newline = true;
696                 }
697
698                 public override void WriteLine (string s)
699                 {
700                         OutputTabs ();
701                         b.WriteLine (s);
702                         newline = true;
703                 }
704
705                 public override void WriteLine (float value)
706                 {
707                         OutputTabs ();
708                         b.WriteLine (value);
709                         newline = true;
710                 }
711
712                 public void WriteLineNoTabs (string s)
713                 {
714                         b.WriteLine (s);
715                         newline = true;
716                 }
717
718                 public override Encoding Encoding {
719                         get {
720                                 return b.Encoding;
721                         }
722                 }
723
724                 int indent;
725                 public int Indent {
726                         get {
727                                 return indent;
728                         }
729                         set {
730                                 indent = value;
731                         }
732                 }
733
734                 public System.IO.TextWriter InnerWriter {
735                         get {
736                                 return b;
737                         }
738                         set {
739                                 b = value;
740                         }
741                 }
742
743                 public override string NewLine {
744                         get {
745                                 return b.NewLine;
746                         }
747                         set {
748                                 b.NewLine = value;
749                         }
750                 }
751
752                 protected HtmlTextWriterTag TagKey {
753                         get {
754                                 if (tagstack_pos == -1)
755                                         throw new InvalidOperationException ();
756
757                                 return tagstack [tagstack_pos].key;
758                         }
759                         set {
760                                 tagstack [tagstack_pos].key = value;
761                                 tagstack [tagstack_pos].name = GetTagName (value);
762                         }
763                 }
764
765                 protected string TagName {
766                         get {
767                                 if (tagstack_pos == -1)
768                                         throw new InvalidOperationException ();
769
770                                 return tagstack [tagstack_pos].name;
771                         }
772                         set {
773                                 tagstack [tagstack_pos].name = value;
774                                 tagstack [tagstack_pos].key = GetTagKey (value);
775                                 if (tagstack [tagstack_pos].key != HtmlTextWriterTag.Unknown)
776                                         tagstack [tagstack_pos].name = GetTagName (tagstack [tagstack_pos].key);
777                         }
778                 }
779
780                 bool TagIgnore {
781                         get {
782                                 if (tagstack_pos == -1)
783                                         throw new InvalidOperationException ();
784
785                                 return tagstack [tagstack_pos].ignore;
786                         }
787
788                         set {
789                                 if (tagstack_pos == -1)
790                                         throw new InvalidOperationException ();
791                                 
792                                 tagstack [tagstack_pos].ignore = value;
793                         }
794                 }
795                 
796                 internal HttpWriter GetHttpWriter ()
797                 {
798                         return b as HttpWriter;
799                 }
800
801                 TextWriter b;
802                 string tab_string;
803                 bool newline;
804
805                 //
806                 // These emulate generic Stack <T>, since we can't use that ;-(. _pos is the current
807                 // element.IE, you edit blah [blah_pos]. I *really* want generics, sigh.
808                 //
809                 AddedStyle [] styles;
810                 AddedAttr [] attrs;
811                 AddedTag [] tagstack;
812
813                 int styles_pos = -1, attrs_pos = -1, tagstack_pos = -1;
814
815                 struct 
816                 AddedTag {
817                         public string name;
818                         public HtmlTextWriterTag key;
819                         public bool ignore;
820                 }
821
822                 struct 
823                 AddedStyle {
824                         public string name;
825                         public HtmlTextWriterStyle key;
826                         public string value;
827                 }
828
829                 struct 
830                 AddedAttr {
831                         public string name;
832                         public HtmlTextWriterAttribute key;
833                         public string value;
834                 }
835
836                 void NextStyleStack ()
837                 {
838                         if (styles == null)
839                                 styles = new AddedStyle [16];
840
841                         if (++styles_pos < styles.Length)
842                                 return;
843
844                         int nsize = styles.Length * 2;
845                         AddedStyle [] ncontents = new AddedStyle [nsize];
846
847                         Array.Copy (styles, ncontents, styles.Length);
848                         styles = ncontents;
849                 }
850
851                 void NextAttrStack ()
852                 {
853                         if (attrs == null)
854                                 attrs = new AddedAttr [16];
855
856                         if (++attrs_pos < attrs.Length)
857                                 return;
858
859                         int nsize = attrs.Length * 2;
860                         AddedAttr [] ncontents = new AddedAttr [nsize];
861
862                         Array.Copy (attrs, ncontents, attrs.Length);
863                         attrs = ncontents;
864                 }
865
866                 void NextTagStack ()
867                 {
868                         if (tagstack == null)
869                                 tagstack = new AddedTag [16];
870
871                         if (++tagstack_pos < tagstack.Length)
872                                 return;
873
874                         int nsize = tagstack.Length * 2;
875                         AddedTag [] ncontents = new AddedTag [nsize];
876
877                         Array.Copy (tagstack, ncontents, tagstack.Length);
878                         tagstack = ncontents;
879                 }
880
881                 public const string DefaultTabString = "\t";
882                 public const char DoubleQuoteChar = '"';
883                 public const string EndTagLeftChars = "</";
884                 public const char EqualsChar = '=';
885                 public const string EqualsDoubleQuoteString = "=\"";
886                 public const string SelfClosingChars = " /";
887                 public const string SelfClosingTagEnd = " />";
888                 public const char SemicolonChar = ';';
889                 public const char SingleQuoteChar = '\'';
890                 public const char SlashChar = '/';
891                 public const char SpaceChar = ' ';
892                 public const char StyleEqualsChar = ':';
893                 public const char TagLeftChar = '<';
894                 public const char TagRightChar = '>';
895
896                 enum TagType {
897                         Block,
898                         Inline,
899                         SelfClosing,
900                 }
901
902
903                 sealed class HtmlTag {
904                         readonly public HtmlTextWriterTag key;
905                         readonly public string name;
906                         readonly public TagType tag_type;
907
908                         public HtmlTag (HtmlTextWriterTag k, string n, TagType tt)
909                         {
910                                 key = k;
911                                 name = n;
912                                 tag_type = tt;
913                         }
914                 }
915
916                 sealed class HtmlStyle {
917                         readonly public HtmlTextWriterStyle key;
918                         readonly public string name;
919
920                         public HtmlStyle (HtmlTextWriterStyle k, string n)
921                         {
922                                 key = k;
923                                 name = n;
924                         }
925                 }
926
927
928                 sealed class HtmlAttribute {
929                         readonly public HtmlTextWriterAttribute key;
930                         readonly public string name;
931
932                         public HtmlAttribute (HtmlTextWriterAttribute k, string n)
933                         {
934                                 key = k;
935                                 name = n;
936                         }
937                 }
938
939                 static HtmlTag [] tags = {
940                         new HtmlTag (HtmlTextWriterTag.Unknown,    String.Empty,        TagType.Block),
941                         new HtmlTag (HtmlTextWriterTag.A,          "a",                 TagType.Inline),
942                         new HtmlTag (HtmlTextWriterTag.Acronym,    "acronym",           TagType.Inline),
943                         new HtmlTag (HtmlTextWriterTag.Address,    "address",           TagType.Block),
944                         new HtmlTag (HtmlTextWriterTag.Area,       "area",              TagType.Block),
945                         new HtmlTag (HtmlTextWriterTag.B,          "b",                 TagType.Inline),
946                         new HtmlTag (HtmlTextWriterTag.Base,       "base",              TagType.SelfClosing),
947                         new HtmlTag (HtmlTextWriterTag.Basefont,   "basefont",          TagType.SelfClosing),
948                         new HtmlTag (HtmlTextWriterTag.Bdo,        "bdo",               TagType.Inline),
949                         new HtmlTag (HtmlTextWriterTag.Bgsound,    "bgsound",           TagType.SelfClosing),
950                         new HtmlTag (HtmlTextWriterTag.Big,        "big",               TagType.Inline),
951                         new HtmlTag (HtmlTextWriterTag.Blockquote, "blockquote",        TagType.Block),
952                         new HtmlTag (HtmlTextWriterTag.Body,       "body",              TagType.Block),
953                         new HtmlTag (HtmlTextWriterTag.Br,         "br",                TagType.Block),
954                         new HtmlTag (HtmlTextWriterTag.Button,     "button",            TagType.Inline),
955                         new HtmlTag (HtmlTextWriterTag.Caption,    "caption",           TagType.Block),
956                         new HtmlTag (HtmlTextWriterTag.Center,     "center",            TagType.Block),
957                         new HtmlTag (HtmlTextWriterTag.Cite,       "cite",              TagType.Inline),
958                         new HtmlTag (HtmlTextWriterTag.Code,       "code",              TagType.Inline),
959                         new HtmlTag (HtmlTextWriterTag.Col,        "col",               TagType.SelfClosing),
960                         new HtmlTag (HtmlTextWriterTag.Colgroup,   "colgroup",          TagType.Block),
961                         new HtmlTag (HtmlTextWriterTag.Dd,         "dd",                TagType.Inline),
962                         new HtmlTag (HtmlTextWriterTag.Del,        "del",               TagType.Inline),
963                         new HtmlTag (HtmlTextWriterTag.Dfn,        "dfn",               TagType.Inline),
964                         new HtmlTag (HtmlTextWriterTag.Dir,        "dir",               TagType.Block),
965                         new HtmlTag (HtmlTextWriterTag.Div,        "div",               TagType.Block),
966                         new HtmlTag (HtmlTextWriterTag.Dl,         "dl",                TagType.Block),
967                         new HtmlTag (HtmlTextWriterTag.Dt,         "dt",                TagType.Inline),
968                         new HtmlTag (HtmlTextWriterTag.Em,         "em",                TagType.Inline),
969                         new HtmlTag (HtmlTextWriterTag.Embed,      "embed",             TagType.SelfClosing),
970                         new HtmlTag (HtmlTextWriterTag.Fieldset,   "fieldset",          TagType.Block),
971                         new HtmlTag (HtmlTextWriterTag.Font,       "font",              TagType.Inline),
972                         new HtmlTag (HtmlTextWriterTag.Form,       "form",              TagType.Block),
973                         new HtmlTag (HtmlTextWriterTag.Frame,      "frame",             TagType.SelfClosing),
974                         new HtmlTag (HtmlTextWriterTag.Frameset,   "frameset",          TagType.Block),
975                         new HtmlTag (HtmlTextWriterTag.H1,         "h1",                TagType.Block),
976                         new HtmlTag (HtmlTextWriterTag.H2,         "h2",                TagType.Block),
977                         new HtmlTag (HtmlTextWriterTag.H3,         "h3",                TagType.Block),
978                         new HtmlTag (HtmlTextWriterTag.H4,         "h4",                TagType.Block),
979                         new HtmlTag (HtmlTextWriterTag.H5,         "h5",                TagType.Block),
980                         new HtmlTag (HtmlTextWriterTag.H6,         "h6",                TagType.Block),
981                         new HtmlTag (HtmlTextWriterTag.Head,       "head",              TagType.Block),
982                         new HtmlTag (HtmlTextWriterTag.Hr,         "hr",                TagType.SelfClosing),
983                         new HtmlTag (HtmlTextWriterTag.Html,       "html",              TagType.Block),
984                         new HtmlTag (HtmlTextWriterTag.I,          "i",                 TagType.Inline),
985                         new HtmlTag (HtmlTextWriterTag.Iframe,     "iframe",            TagType.Block),
986                         new HtmlTag (HtmlTextWriterTag.Img,        "img",               TagType.SelfClosing),
987                         new HtmlTag (HtmlTextWriterTag.Input,      "input",             TagType.SelfClosing),
988                         new HtmlTag (HtmlTextWriterTag.Ins,        "ins",               TagType.Inline),
989                         new HtmlTag (HtmlTextWriterTag.Isindex,    "isindex",           TagType.SelfClosing),
990                         new HtmlTag (HtmlTextWriterTag.Kbd,        "kbd",               TagType.Inline),
991                         new HtmlTag (HtmlTextWriterTag.Label,      "label",             TagType.Inline),
992                         new HtmlTag (HtmlTextWriterTag.Legend,     "legend",            TagType.Block),
993                         new HtmlTag (HtmlTextWriterTag.Li,         "li",                TagType.Inline),
994                         new HtmlTag (HtmlTextWriterTag.Link,       "link",              TagType.SelfClosing),
995                         new HtmlTag (HtmlTextWriterTag.Map,        "map",               TagType.Block),
996                         new HtmlTag (HtmlTextWriterTag.Marquee,    "marquee",           TagType.Block),
997                         new HtmlTag (HtmlTextWriterTag.Menu,       "menu",              TagType.Block),
998                         new HtmlTag (HtmlTextWriterTag.Meta,       "meta",              TagType.SelfClosing),
999                         new HtmlTag (HtmlTextWriterTag.Nobr,       "nobr",              TagType.Inline),
1000                         new HtmlTag (HtmlTextWriterTag.Noframes,   "noframes",          TagType.Block),
1001                         new HtmlTag (HtmlTextWriterTag.Noscript,   "noscript",          TagType.Block),
1002                         new HtmlTag (HtmlTextWriterTag.Object,     "object",            TagType.Block),
1003                         new HtmlTag (HtmlTextWriterTag.Ol,         "ol",                TagType.Block),
1004                         new HtmlTag (HtmlTextWriterTag.Option,     "option",            TagType.Block),
1005                         new HtmlTag (HtmlTextWriterTag.P,          "p",                 TagType.Inline),
1006                         new HtmlTag (HtmlTextWriterTag.Param,      "param",             TagType.Block),
1007                         new HtmlTag (HtmlTextWriterTag.Pre,        "pre",               TagType.Block),
1008                         new HtmlTag (HtmlTextWriterTag.Q,          "q",                 TagType.Inline),
1009                         new HtmlTag (HtmlTextWriterTag.Rt,         "rt",                TagType.Block),
1010                         new HtmlTag (HtmlTextWriterTag.Ruby,       "ruby",              TagType.Block),
1011                         new HtmlTag (HtmlTextWriterTag.S,          "s",                 TagType.Inline),
1012                         new HtmlTag (HtmlTextWriterTag.Samp,       "samp",              TagType.Inline),
1013                         new HtmlTag (HtmlTextWriterTag.Script,     "script",            TagType.Block),
1014                         new HtmlTag (HtmlTextWriterTag.Select,     "select",            TagType.Block),
1015                         new HtmlTag (HtmlTextWriterTag.Small,      "small",             TagType.Block),
1016                         new HtmlTag (HtmlTextWriterTag.Span,       "span",              TagType.Inline),
1017                         new HtmlTag (HtmlTextWriterTag.Strike,     "strike",            TagType.Inline),
1018                         new HtmlTag (HtmlTextWriterTag.Strong,     "strong",            TagType.Inline),
1019                         new HtmlTag (HtmlTextWriterTag.Style,      "style",             TagType.Block),
1020                         new HtmlTag (HtmlTextWriterTag.Sub,        "sub",               TagType.Inline),
1021                         new HtmlTag (HtmlTextWriterTag.Sup,        "sup",               TagType.Inline),
1022                         new HtmlTag (HtmlTextWriterTag.Table,      "table",             TagType.Block),
1023                         new HtmlTag (HtmlTextWriterTag.Tbody,      "tbody",             TagType.Block),
1024                         new HtmlTag (HtmlTextWriterTag.Td,         "td",                TagType.Inline),
1025                         new HtmlTag (HtmlTextWriterTag.Textarea,   "textarea",          TagType.Inline),
1026                         new HtmlTag (HtmlTextWriterTag.Tfoot,      "tfoot",             TagType.Block),
1027                         new HtmlTag (HtmlTextWriterTag.Th,         "th",                TagType.Inline),
1028                         new HtmlTag (HtmlTextWriterTag.Thead,      "thead",             TagType.Block),
1029                         new HtmlTag (HtmlTextWriterTag.Title,      "title",             TagType.Block),
1030                         new HtmlTag (HtmlTextWriterTag.Tr,         "tr",                TagType.Block),
1031                         new HtmlTag (HtmlTextWriterTag.Tt,         "tt",                TagType.Inline),
1032                         new HtmlTag (HtmlTextWriterTag.U,          "u",                 TagType.Inline),
1033                         new HtmlTag (HtmlTextWriterTag.Ul,         "ul",                TagType.Block),
1034                         new HtmlTag (HtmlTextWriterTag.Var,        "var",               TagType.Inline),
1035                         new HtmlTag (HtmlTextWriterTag.Wbr,        "wbr",               TagType.SelfClosing),
1036                         new HtmlTag (HtmlTextWriterTag.Xml,        "xml",               TagType.Block),
1037                 };
1038
1039                 static HtmlAttribute [] htmlattrs = {
1040                         new HtmlAttribute (HtmlTextWriterAttribute.Accesskey,         "accesskey"),
1041                         new HtmlAttribute (HtmlTextWriterAttribute.Align,             "align"),
1042                         new HtmlAttribute (HtmlTextWriterAttribute.Alt,               "alt"),
1043                         new HtmlAttribute (HtmlTextWriterAttribute.Background,        "background"),
1044                         new HtmlAttribute (HtmlTextWriterAttribute.Bgcolor,           "bgcolor"),
1045                         new HtmlAttribute (HtmlTextWriterAttribute.Border,            "border"),
1046                         new HtmlAttribute (HtmlTextWriterAttribute.Bordercolor,       "bordercolor"),
1047                         new HtmlAttribute (HtmlTextWriterAttribute.Cellpadding,       "cellpadding"),
1048                         new HtmlAttribute (HtmlTextWriterAttribute.Cellspacing,       "cellspacing"),
1049                         new HtmlAttribute (HtmlTextWriterAttribute.Checked,           "checked"),
1050                         new HtmlAttribute (HtmlTextWriterAttribute.Class,             "class"),
1051                         new HtmlAttribute (HtmlTextWriterAttribute.Cols,              "cols"),
1052                         new HtmlAttribute (HtmlTextWriterAttribute.Colspan,           "colspan"),
1053                         new HtmlAttribute (HtmlTextWriterAttribute.Disabled,          "disabled"),
1054                         new HtmlAttribute (HtmlTextWriterAttribute.For,               "for"),
1055                         new HtmlAttribute (HtmlTextWriterAttribute.Height,            "height"),
1056                         new HtmlAttribute (HtmlTextWriterAttribute.Href,              "href"),
1057                         new HtmlAttribute (HtmlTextWriterAttribute.Id,                "id"),
1058                         new HtmlAttribute (HtmlTextWriterAttribute.Maxlength,         "maxlength"),
1059                         new HtmlAttribute (HtmlTextWriterAttribute.Multiple,          "multiple"),
1060                         new HtmlAttribute (HtmlTextWriterAttribute.Name,              "name"),
1061                         new HtmlAttribute (HtmlTextWriterAttribute.Nowrap,            "nowrap"),
1062                         new HtmlAttribute (HtmlTextWriterAttribute.Onchange,          "onchange"),
1063                         new HtmlAttribute (HtmlTextWriterAttribute.Onclick,           "onclick"),
1064                         new HtmlAttribute (HtmlTextWriterAttribute.ReadOnly,          "readonly"),
1065                         new HtmlAttribute (HtmlTextWriterAttribute.Rows,              "rows"),
1066                         new HtmlAttribute (HtmlTextWriterAttribute.Rowspan,           "rowspan"),
1067                         new HtmlAttribute (HtmlTextWriterAttribute.Rules,             "rules"),
1068                         new HtmlAttribute (HtmlTextWriterAttribute.Selected,          "selected"),
1069                         new HtmlAttribute (HtmlTextWriterAttribute.Size,              "size"),
1070                         new HtmlAttribute (HtmlTextWriterAttribute.Src,               "src"),
1071                         new HtmlAttribute (HtmlTextWriterAttribute.Style,             "style"),
1072                         new HtmlAttribute (HtmlTextWriterAttribute.Tabindex,          "tabindex"),
1073                         new HtmlAttribute (HtmlTextWriterAttribute.Target,            "target"),
1074                         new HtmlAttribute (HtmlTextWriterAttribute.Title,             "title"),
1075                         new HtmlAttribute (HtmlTextWriterAttribute.Type,              "type"),
1076                         new HtmlAttribute (HtmlTextWriterAttribute.Valign,            "valign"),
1077                         new HtmlAttribute (HtmlTextWriterAttribute.Value,             "value"),
1078                         new HtmlAttribute (HtmlTextWriterAttribute.Width,             "width"),
1079                         new HtmlAttribute (HtmlTextWriterAttribute.Wrap,              "wrap"),
1080                         new HtmlAttribute (HtmlTextWriterAttribute.Abbr,              "abbr"),
1081                         new HtmlAttribute (HtmlTextWriterAttribute.AutoComplete,      "autocomplete"),
1082                         new HtmlAttribute (HtmlTextWriterAttribute.Axis,              "axis"),
1083                         new HtmlAttribute (HtmlTextWriterAttribute.Content,           "content"),
1084                         new HtmlAttribute (HtmlTextWriterAttribute.Coords,            "coords"),
1085                         new HtmlAttribute (HtmlTextWriterAttribute.DesignerRegion,    "_designerregion"),
1086                         new HtmlAttribute (HtmlTextWriterAttribute.Dir,               "dir"),
1087                         new HtmlAttribute (HtmlTextWriterAttribute.Headers,           "headers"),
1088                         new HtmlAttribute (HtmlTextWriterAttribute.Longdesc,          "longdesc"),
1089                         new HtmlAttribute (HtmlTextWriterAttribute.Rel,               "rel"),
1090                         new HtmlAttribute (HtmlTextWriterAttribute.Scope,             "scope"),
1091                         new HtmlAttribute (HtmlTextWriterAttribute.Shape,             "shape"),
1092                         new HtmlAttribute (HtmlTextWriterAttribute.Usemap,            "usemap"),
1093                         new HtmlAttribute (HtmlTextWriterAttribute.VCardName,         "vcard_name"),
1094                 };
1095
1096                 static HtmlStyle [] htmlstyles = {
1097                         new HtmlStyle (HtmlTextWriterStyle.BackgroundColor,    "background-color"),
1098                         new HtmlStyle (HtmlTextWriterStyle.BackgroundImage,    "background-image"),
1099                         new HtmlStyle (HtmlTextWriterStyle.BorderCollapse,     "border-collapse"),
1100                         new HtmlStyle (HtmlTextWriterStyle.BorderColor,        "border-color"),
1101                         new HtmlStyle (HtmlTextWriterStyle.BorderStyle,        "border-style"),
1102                         new HtmlStyle (HtmlTextWriterStyle.BorderWidth,        "border-width"),
1103                         new HtmlStyle (HtmlTextWriterStyle.Color,              "color"),
1104                         new HtmlStyle (HtmlTextWriterStyle.FontFamily,         "font-family"),
1105                         new HtmlStyle (HtmlTextWriterStyle.FontSize,           "font-size"),
1106                         new HtmlStyle (HtmlTextWriterStyle.FontStyle,          "font-style"),
1107                         new HtmlStyle (HtmlTextWriterStyle.FontWeight,         "font-weight"),
1108                         new HtmlStyle (HtmlTextWriterStyle.Height,             "height"),
1109                         new HtmlStyle (HtmlTextWriterStyle.TextDecoration,     "text-decoration"),
1110                         new HtmlStyle (HtmlTextWriterStyle.Width,              "width"),
1111                         new HtmlStyle (HtmlTextWriterStyle.ListStyleImage,     "list-style-image"),
1112                         new HtmlStyle (HtmlTextWriterStyle.ListStyleType,      "list-style-type"),
1113                         new HtmlStyle (HtmlTextWriterStyle.Cursor,             "cursor"),
1114                         new HtmlStyle (HtmlTextWriterStyle.Direction,          "direction"),
1115                         new HtmlStyle (HtmlTextWriterStyle.Display,            "display"),
1116                         new HtmlStyle (HtmlTextWriterStyle.Filter,             "filter"),
1117                         new HtmlStyle (HtmlTextWriterStyle.FontVariant,        "font-variant"),
1118                         new HtmlStyle (HtmlTextWriterStyle.Left,               "left"),
1119                         new HtmlStyle (HtmlTextWriterStyle.Margin,             "margin"),
1120                         new HtmlStyle (HtmlTextWriterStyle.MarginBottom,       "margin-bottom"),
1121                         new HtmlStyle (HtmlTextWriterStyle.MarginLeft,         "margin-left"),
1122                         new HtmlStyle (HtmlTextWriterStyle.MarginRight,        "margin-right"),
1123                         new HtmlStyle (HtmlTextWriterStyle.MarginTop,          "margin-top"),
1124                         new HtmlStyle (HtmlTextWriterStyle.Overflow,           "overflow"),
1125                         new HtmlStyle (HtmlTextWriterStyle.OverflowX,          "overflow-x"),
1126                         new HtmlStyle (HtmlTextWriterStyle.OverflowY,          "overflow-y"),
1127                         new HtmlStyle (HtmlTextWriterStyle.Padding,            "padding"),
1128                         new HtmlStyle (HtmlTextWriterStyle.PaddingBottom,      "padding-bottom"),
1129                         new HtmlStyle (HtmlTextWriterStyle.PaddingLeft,        "padding-left"),
1130                         new HtmlStyle (HtmlTextWriterStyle.PaddingRight,       "padding-right"),
1131                         new HtmlStyle (HtmlTextWriterStyle.PaddingTop,         "padding-top"),
1132                         new HtmlStyle (HtmlTextWriterStyle.Position,           "position"),
1133                         new HtmlStyle (HtmlTextWriterStyle.TextAlign,          "text-align"),
1134                         new HtmlStyle (HtmlTextWriterStyle.VerticalAlign,      "vertical-align"),
1135                         new HtmlStyle (HtmlTextWriterStyle.TextOverflow,       "text-overflow"),
1136                         new HtmlStyle (HtmlTextWriterStyle.Top,                "top"),
1137                         new HtmlStyle (HtmlTextWriterStyle.Visibility,         "visibility"),
1138                         new HtmlStyle (HtmlTextWriterStyle.WhiteSpace,         "white-space"),
1139                         new HtmlStyle (HtmlTextWriterStyle.ZIndex,             "z-index"),
1140                 };
1141
1142                 public virtual bool IsValidFormAttribute (string attribute)
1143                 {
1144                         return true;
1145                 }
1146
1147                 // writes <br />
1148                 public virtual void WriteBreak ()
1149                 {
1150                         string br = GetTagName (HtmlTextWriterTag.Br);
1151                         WriteBeginTag (br);
1152                         Write (SelfClosingTagEnd);
1153                 }
1154
1155                 public virtual void WriteEncodedText (string text)
1156                 {
1157                         Write (HttpUtility.HtmlEncode (text));
1158                 }
1159
1160                 [MonoNotSupported ("")]
1161                 public virtual void WriteEncodedUrl (string url)
1162                 {
1163                         // WriteUrlEncodedString (url, false);
1164                         throw new NotImplementedException ();
1165                 }
1166
1167                 [MonoNotSupported ("")]
1168                 public virtual void WriteEncodedUrlParameter (string urlText)
1169                 {
1170                         // WriteUrlEncodedString (urlText, true);
1171                         throw new NotImplementedException ();
1172                 }
1173
1174                 [MonoNotSupported ("")]
1175                 protected void WriteUrlEncodedString (string text, bool argument)
1176                 {
1177                         throw new NotImplementedException ();
1178                 }
1179
1180                 [MonoNotSupported ("")]
1181                 public virtual void EnterStyle (Style style)
1182                 {
1183                         throw new NotImplementedException ();
1184                 }
1185
1186                 [MonoNotSupported ("")]
1187                 public virtual void EnterStyle (Style style, HtmlTextWriterTag tag)
1188                 {
1189                         throw new NotImplementedException ();
1190                 }
1191
1192                 [MonoNotSupported ("")]
1193                 public virtual void ExitStyle (Style style)
1194                 {
1195                         throw new NotImplementedException ();
1196                 }
1197
1198                 [MonoNotSupported ("")]
1199                 public virtual void ExitStyle (Style style, HtmlTextWriterTag tag)
1200                 {
1201                         throw new NotImplementedException ();
1202                 }
1203                 
1204                 public virtual void BeginRender ()
1205                 {
1206                 }
1207
1208                 public virtual void EndRender ()
1209                 {
1210                 }
1211         }
1212 }