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