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