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