2009-02-26 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / HtmlTextWriter.cs
index f2858da6ef3fbf7b6ad4ebd0a7dad8d0c0942de0..ab2e7b7dc7a774c8410a9077d2d6ead78916a762 100644 (file)
@@ -31,66 +31,98 @@ using System.Globalization;
 using System.Collections;
 using System.Security.Permissions;
 using System.Text;
+using System.Web.UI.WebControls;
 
 namespace System.Web.UI {
-       
+
        // CAS
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        public class HtmlTextWriter : TextWriter {
 
 
+               readonly static Hashtable _tagTable;
+               readonly static Hashtable _attributeTable;
+               readonly static Hashtable _styleTable;
+
+               static HtmlTextWriter ()
+               {
+#if NET_2_0
+                       _tagTable = new Hashtable (tags.Length, StringComparer.OrdinalIgnoreCase);
+                       _attributeTable = new Hashtable (htmlattrs.Length, StringComparer.OrdinalIgnoreCase);
+                       _styleTable = new Hashtable (htmlstyles.Length, StringComparer.OrdinalIgnoreCase);
+#else
+                       _tagTable = new Hashtable (tags.Length, 
+                               CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
+                       
+                       _attributeTable = new Hashtable (htmlattrs.Length, 
+                               CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
+                       
+                       _styleTable = new Hashtable (htmlstyles.Length, 
+                               CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
+#endif
+                       foreach (HtmlTag tag in tags)
+                               _tagTable.Add (tag.name, tag);
+
+                       foreach (HtmlAttribute attr in htmlattrs)
+                               _attributeTable.Add (attr.name, attr);
+
+                       foreach (HtmlStyle style in htmlstyles)
+                               _styleTable.Add (style.name, style);
+               }
+
                public HtmlTextWriter (TextWriter writer) : this (writer, DefaultTabString)
                {
                }
-       
+
                public HtmlTextWriter (TextWriter writer, string tabString)
                {
-                       if (writer == null)
-                               throw new ArgumentNullException ();
-
                        b = writer;
                        tab_string = tabString;
                }
 
-               internal static string StaticGetStyleName (System.Web.UI.HtmlTextWriterStyle styleKey) 
+               internal static string StaticGetStyleName (System.Web.UI.HtmlTextWriterStyle styleKey)
                {
                        if ((int) styleKey < htmlstyles.Length)
                                return htmlstyles [(int) styleKey].name;
 
                        return null;
                }
-               
-               [MonoTODO]
+
+               [MonoTODO ("Does nothing")]
                protected static void RegisterAttribute (string name, HtmlTextWriterAttribute key)
                {
                }
-               
-               [MonoTODO]
+
+               [MonoTODO ("Does nothing")]
                protected static void RegisterStyle (string name, HtmlTextWriterStyle key)
                {
                }
-               
-               [MonoTODO]
+
+               [MonoTODO ("Does nothing")]
                protected static void RegisterTag (string name, HtmlTextWriterTag key)
                {
                }
-               
-       
+
+
                public virtual void AddAttribute (HtmlTextWriterAttribute key, string value, bool fEncode)
                {
                        if (fEncode)
-                               value = EncodeAttributeValue (key, value);
+                               value = HttpUtility.HtmlAttributeEncode (value);
+
                        AddAttribute (GetAttributeName (key), value, key);
                }
-               
-               
+
+
                public virtual void AddAttribute (HtmlTextWriterAttribute key, string value)
                {
-                       AddAttribute (key, value, true);
+                       if ((key != HtmlTextWriterAttribute.Name) && (key != HtmlTextWriterAttribute.Id))
+                               value = HttpUtility.HtmlAttributeEncode (value);
+
+                       AddAttribute (GetAttributeName (key), value, key);
                }
-       
-       
+
+
                public virtual void AddAttribute (string name, string value, bool fEncode)
                {
                        if (fEncode)
@@ -98,75 +130,91 @@ namespace System.Web.UI {
 
                        AddAttribute (name, value, GetAttributeKey (name));
                }
-               
+
                public virtual void AddAttribute (string name, string value)
                {
-                       AddAttribute (name, value, true);
+                       HtmlTextWriterAttribute key = GetAttributeKey (name);
+
+                       if ((key != HtmlTextWriterAttribute.Name) && (key != HtmlTextWriterAttribute.Id))
+                               value = HttpUtility.HtmlAttributeEncode (value);
+
+                       AddAttribute (name, value, key);
                }
-       
+
                protected virtual void AddAttribute (string name, string value, HtmlTextWriterAttribute key)
                {
                        NextAttrStack ();
+#if TARGET_JVM
+                       if (attrs [attrs_pos] == null)
+                               attrs [attrs_pos] = new AddedAttr ();
+#endif
                        attrs [attrs_pos].name = name;
                        attrs [attrs_pos].value = value;
                        attrs [attrs_pos].key = key;
                }
-               
-               
+
+
                protected virtual void AddStyleAttribute (string name, string value, HtmlTextWriterStyle key)
                {
                        NextStyleStack ();
+#if TARGET_JVM
+                       if (styles [styles_pos] == null)
+                               styles [styles_pos] = new AddedStyle ();
+#endif
                        styles [styles_pos].name = name;
+#if NET_2_0
+                       value = HttpUtility.HtmlAttributeEncode (value);
+#endif
                        styles [styles_pos].value = value;
                        styles [styles_pos].key = key;
                }
-               
+
 
                public virtual void AddStyleAttribute (string name, string value)
                {
                        AddStyleAttribute (name, value, GetStyleKey (name));
                }
-               
+
                public virtual void AddStyleAttribute (HtmlTextWriterStyle key, string value)
                {
                        AddStyleAttribute (GetStyleName (key), value, key);
                }
-       
+
                public override void Close ()
                {
-                       b.Close ();     
+                       b.Close ();
                }
 
                protected virtual string EncodeAttributeValue (HtmlTextWriterAttribute attrKey, string value)
                {
-                       return HttpUtility.HtmlEncode (value);
+                       return HttpUtility.HtmlAttributeEncode (value);
                }
-               
+
                protected string EncodeAttributeValue (string value, bool fEncode)
                {
                        if (fEncode)
-                               return HttpUtility.HtmlEncode (value);
+                               return HttpUtility.HtmlAttributeEncode (value);
                        return value;
                }
-               
+
                protected string EncodeUrl (string url)
                {
                        return HttpUtility.UrlPathEncode (url);
                }
-               
+
 
                protected virtual void FilterAttributes ()
                {
                        AddedAttr style_attr = new AddedAttr ();
-                       
-                       for (int i = 0; i <= attrs_pos; i ++) {
+
+                       for (int i = 0; i <= attrs_pos; i++) {
                                AddedAttr a = attrs [i];
                                if (OnAttributeRender (a.name, a.value, a.key)) {
                                        if (a.key == HtmlTextWriterAttribute.Style) {
                                                style_attr = a;
                                                continue;
                                        }
-                                       
+
                                        WriteAttribute (a.name, a.value, false);
                                }
                        }
@@ -175,43 +223,41 @@ namespace System.Web.UI {
                                Write (SpaceChar);
                                Write ("style");
                                Write (EqualsDoubleQuoteString);
-                               
-                               
-                               for (int i = 0; i <= styles_pos; i ++) {
+
+
+                               for (int i = 0; i <= styles_pos; i++) {
                                        AddedStyle a = styles [i];
-                                       if (OnStyleAttributeRender (a.name, a.value, a.key))
+                                       if (OnStyleAttributeRender (a.name, a.value, a.key)) {
+#if NET_2_0
+                                               if (a.key == HtmlTextWriterStyle.BackgroundImage) {
+                                                       a.value = String.Concat ("url(", HttpUtility.UrlPathEncode (a.value), ")");
+                                               }
+#endif
                                                WriteStyleAttribute (a.name, a.value, false);
+                                       }
                                }
 
-                               Write (style_attr.value);                               
+                               Write (style_attr.value);
                                Write (DoubleQuoteChar);
                        }
 
                        styles_pos = attrs_pos = -1;
                }
-       
+
                public override void Flush ()
                {
                        b.Flush ();
                }
 
-               [MonoTODO]
                protected HtmlTextWriterAttribute GetAttributeKey (string attrName)
                {
-                       // I don't think we want to binary search
-                       // because there might be something added to
-                       // the enum later. Do we really need anything
-                       // faster than a linear search?
-                       
-                       foreach (HtmlAttribute t in htmlattrs) {
-                               if (String.Compare(t.name, attrName, true, CultureInfo.InvariantCulture) == 0)
-                                       return t.key;
-                       }
+                       object attribute = _attributeTable [attrName];
+                       if (attribute == null)
+                               return (HtmlTextWriterAttribute) (-1);
 
-                       return (HtmlTextWriterAttribute)(-1);           
+                       return (HtmlTextWriterAttribute) ((HtmlAttribute) attribute).key;
                }
 
-               [MonoTODO]
                protected string GetAttributeName (HtmlTextWriterAttribute attrKey)
                {
                        if ((int) attrKey < htmlattrs.Length)
@@ -219,43 +265,28 @@ namespace System.Web.UI {
 
                        return null;
                }
-               
-               [MonoTODO]
+
                protected HtmlTextWriterStyle GetStyleKey (string styleName)
                {
-                       // I don't think we want to binary search
-                       // because there might be something added to
-                       // the enum later. Do we really need anything
-                       // faster than a linear search?
-                       
-                       foreach (HtmlStyle t in htmlstyles) {
-                               if (String.Compare(t.name, styleName, true, CultureInfo.InvariantCulture) == 0)
-                                       return t.key;
-                       }
+                       object style = _styleTable [styleName];
+                       if (style == null)
+                               return (HtmlTextWriterStyle) (-1);
 
-                       return (HtmlTextWriterStyle)(-1);                       
+                       return (HtmlTextWriterStyle) ((HtmlStyle) style).key;
                }
-               
-               [MonoTODO]
+
                protected string GetStyleName (HtmlTextWriterStyle styleKey)
                {
                        return StaticGetStyleName (styleKey);
                }
-               
-               [MonoTODO]
-               protected virtual HtmlTextWriterTag GetTagKey (string tagName) 
+
+               protected virtual HtmlTextWriterTag GetTagKey (string tagName)
                {
-                       // I don't think we want to binary search
-                       // because there might be something added to
-                       // the enum later. Do we really need anything
-                       // faster than a linear search?
-                       
-                       foreach (HtmlTag t in tags) {
-                               if (String.Compare(t.name, tagName, true, CultureInfo.InvariantCulture) == 0)
-                                       return t.key;
-                       }
+                       object tag = _tagTable [tagName];
+                       if (tag == null)
+                               return HtmlTextWriterTag.Unknown;
 
-                       return HtmlTextWriterTag.Unknown;
+                       return (HtmlTextWriterTag) ((HtmlTag) tag).key;
                }
 
                internal static string StaticGetTagName (HtmlTextWriterTag tagKey)
@@ -263,11 +294,10 @@ namespace System.Web.UI {
                        if ((int) tagKey < tags.Length)
                                return tags [(int) tagKey].name;
 
-                       return null;    
+                       return null;
                }
-               
-               
-               [MonoTODO]
+
+
                protected virtual string GetTagName (HtmlTextWriterTag tagKey)
                {
                        if ((int) tagKey < tags.Length)
@@ -275,17 +305,17 @@ namespace System.Web.UI {
 
                        return null;
                }
-               
+
                protected bool IsAttributeDefined (HtmlTextWriterAttribute key)
                {
                        string value;
                        return IsAttributeDefined (key, out value);
                }
-       
+
                protected bool IsAttributeDefined (HtmlTextWriterAttribute key, out string value)
                {
-                       for (int i = 0; i <= attrs_pos; i ++)
-                               if (attrs [i].key == key){
+                       for (int i = 0; i <= attrs_pos; i++)
+                               if (attrs [i].key == key) {
                                        value = attrs [i].value;
                                        return true;
                                }
@@ -293,17 +323,17 @@ namespace System.Web.UI {
                        value = null;
                        return false;
                }
-               
+
                protected bool IsStyleAttributeDefined (HtmlTextWriterStyle key)
                {
                        string value;
                        return IsStyleAttributeDefined (key, out value);
                }
-       
+
                protected bool IsStyleAttributeDefined (HtmlTextWriterStyle key, out string value)
                {
-                       for (int i = 0; i <= styles_pos; i ++)
-                               if (styles [i].key == key){
+                       for (int i = 0; i <= styles_pos; i++)
+                               if (styles [i].key == key) {
                                        value = styles [i].value;
                                        return true;
                                }
@@ -311,45 +341,45 @@ namespace System.Web.UI {
                        value = null;
                        return false;
                }
-               
+
                protected virtual bool OnAttributeRender (string name, string value, HtmlTextWriterAttribute key)
                {
                        return true;
                }
-               
+
                protected virtual bool OnStyleAttributeRender (string name, string value, HtmlTextWriterStyle key)
                {
                        return true;
                }
-               
+
                protected virtual bool OnTagRender (string name, HtmlTextWriterTag key)
                {
                        return true;
                }
-               
-       
+
+
                protected virtual void OutputTabs ()
                {
-                       if (! newline)
+                       if (!newline)
                                return;
                        newline = false;
 
-                       for (int i = 0; i < Indent; i ++)
+                       for (int i = 0; i < Indent; i++)
                                b.Write (tab_string);
                }
-       
 
-                       
+
+
                protected string PopEndTag ()
                {
                        if (tagstack_pos == -1)
                                throw new InvalidOperationException ();
-                       
+
                        string s = TagName;
-                       tagstack_pos --;
+                       tagstack_pos--;
                        return s;
                }
-               
+
                protected void PushEndTag (string endTag)
                {
                        NextTagStack ();
@@ -361,23 +391,23 @@ namespace System.Web.UI {
                        NextTagStack ();
                        TagKey = t;
                }
-               
+
 
                protected virtual string RenderAfterContent ()
                {
                        return null;
                }
-               
+
                protected virtual string RenderAfterTag ()
                {
                        return null;
                }
-               
+
                protected virtual string RenderBeforeContent ()
                {
                        return null;
                }
-                       
+
                protected virtual string RenderBeforeTag ()
                {
                        return null;
@@ -385,22 +415,20 @@ namespace System.Web.UI {
 
                public virtual void RenderBeginTag (string tagName)
                {
-                       if (! OnTagRender (tagName, GetTagKey (tagName)))
-                               return;
+                       bool ignore = !OnTagRender (tagName, GetTagKey (tagName));
 
                        PushEndTag (tagName);
-                       
+                       TagIgnore = ignore;
                        DoBeginTag ();
                }
-               
+
                public virtual void RenderBeginTag (HtmlTextWriterTag tagKey)
                {
-                       if (! OnTagRender (GetTagName (tagKey), tagKey))
-                               return;
+                       bool ignore = !OnTagRender (GetTagName (tagKey), tagKey);
 
                        PushEndTag (tagKey);
-
                        DoBeginTag ();
+                       TagIgnore = ignore;
                }
 
                void WriteIfNotNull (string s)
@@ -408,61 +436,67 @@ namespace System.Web.UI {
                        if (s != null)
                                Write (s);
                }
-               
+
 
                void DoBeginTag ()
                {
                        WriteIfNotNull (RenderBeforeTag ());
-                       WriteBeginTag (TagName);
-                       FilterAttributes ();
-
-                       HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
-
-                       switch (tags [(int) key].tag_type) {
-                       case TagType.Inline:
-                               Write (TagRightChar);
-                               break;
-                       case TagType.Block:
-                               Write (TagRightChar);
-                               WriteLine ();
-                               Indent ++;
-                               break;
-                       case TagType.SelfClosing:
-                               Write (SelfClosingTagEnd);
-                               break;
+                       if (!TagIgnore) {
+                               WriteBeginTag (TagName);
+                               FilterAttributes ();
+
+                               HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
+
+                               switch (tags [(int) key].tag_type) {
+                                       case TagType.Inline:
+                                               Write (TagRightChar);
+                                               break;
+                                       case TagType.Block:
+                                               Write (TagRightChar);
+                                               WriteLine ();
+                                               Indent++;
+                                               break;
+                                       case TagType.SelfClosing:
+                                               Write (SelfClosingTagEnd);
+                                               break;
+                               }
                        }
                        
                        // FIXME what do i do for self close here?
                        WriteIfNotNull (RenderBeforeContent ());
                }
-               
+
 
                public virtual void RenderEndTag ()
                {
+                       
                        // FIXME what do i do for self close here?
                        WriteIfNotNull (RenderAfterContent ());
-                       
-                       HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
-
-                       switch (tags [(int) key].tag_type) {
-                       case TagType.Inline:
-                               WriteEndTag (TagName);
-                               break;
-                       case TagType.Block:
-                               Indent --;
-                               WriteLineNoTabs ("");
-                               WriteEndTag (TagName);
-                               
-                               break;
-                       case TagType.SelfClosing:
-                               // NADA
-                               break;
+
+                       if (!TagIgnore) {
+                               HtmlTextWriterTag key = (int) TagKey < tags.Length ? TagKey : HtmlTextWriterTag.Unknown;
+
+                               switch (tags [(int) key].tag_type) {
+                                       case TagType.Inline:
+                                               WriteEndTag (TagName);
+                                               break;
+                                       case TagType.Block:
+                                               Indent--;
+                                               WriteLineNoTabs ("");
+                                               WriteEndTag (TagName);
+
+                                               break;
+                                       case TagType.SelfClosing:
+                                               // NADA
+                                               break;
+                               }
                        }
+                       
                        WriteIfNotNull (RenderAfterTag ());
 
                        PopEndTag ();
                }
-               
+
 
                public virtual void WriteAttribute (string name, string value, bool fEncode)
                {
@@ -475,88 +509,83 @@ namespace System.Web.UI {
                                Write (DoubleQuoteChar);
                        }
                }
-               
-       
+
+
                public virtual void WriteBeginTag (string tagName)
                {
                        Write (TagLeftChar);
                        Write (tagName);
                }
-               
+
                public virtual void WriteEndTag (string tagName)
                {
                        Write (EndTagLeftChars);
                        Write (tagName);
-                       Write (TagRightChar);   
+                       Write (TagRightChar);
                }
-               
+
                public virtual void WriteFullBeginTag (string tagName)
                {
                        Write (TagLeftChar);
                        Write (tagName);
                        Write (TagRightChar);
                }
-                       
+
                public virtual void WriteStyleAttribute (string name, string value)
                {
-                       WriteStyleAttribute (name, value, true);
+                       WriteStyleAttribute (name, value, false);
                }
 
                public virtual void WriteStyleAttribute (string name, string value, bool fEncode)
                {
-#if NET_2_0
-                       if (name == "background-image") {
-                               value = String.Concat ("url(", value, ")");
-                       }
-#endif
                        Write (name);
                        Write (StyleEqualsChar);
                        Write (EncodeAttributeValue (value, fEncode));
                        Write (SemicolonChar);
                }
-               
+
                public override void Write (char [] buffer, int index, int count)
                {
                        OutputTabs ();
                        b.Write (buffer, index, count);
                }
-       
+
                public override void Write (double value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public override void Write (char value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public override void Write (char [] buffer)
                {
                        OutputTabs ();
                        b.Write (buffer);
                }
-       
+
                public override void Write (int value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public override void Write (string format, object arg0)
                {
                        OutputTabs ();
                        b.Write (format, arg0);
                }
-       
+
                public override void Write (string format, object arg0, object arg1)
                {
                        OutputTabs ();
                        b.Write (format, arg0, arg1);
                }
-       
+
                public override void Write (string format, params object [] args)
                {
                        OutputTabs ();
@@ -568,34 +597,34 @@ namespace System.Web.UI {
                        OutputTabs ();
                        b.Write (s);
                }
-               
+
                public override void Write (long value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public override void Write (object value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-               
+
                public override void Write (float value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public override void Write (bool value)
                {
                        OutputTabs ();
                        b.Write (value);
                }
-       
+
                public virtual void WriteAttribute (string name, string value)
                {
-                       WriteAttribute (name, value, true);
+                       WriteAttribute (name, value, false);
                }
 
                public override void WriteLine (char value)
@@ -604,84 +633,84 @@ namespace System.Web.UI {
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine (long value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine (object value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
-                       newline = true; 
+                       newline = true;
                }
-       
+
                public override void WriteLine (double value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine (char [] buffer, int index, int count)
                {
                        OutputTabs ();
                        b.WriteLine (buffer, index, count);
                        newline = true;
                }
-       
+
                public override void WriteLine (char [] buffer)
                {
                        OutputTabs ();
                        b.WriteLine (buffer);
                        newline = true;
                }
-               
+
                public override void WriteLine (bool value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine ()
                {
                        OutputTabs ();
                        b.WriteLine ();
                        newline = true;
                }
-       
+
                public override void WriteLine (int value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine (string format, object arg0, object arg1)
                {
                        OutputTabs ();
                        b.WriteLine (format, arg0, arg1);
                        newline = true;
                }
-       
+
                public override void WriteLine (string format, object arg0)
                {
                        OutputTabs ();
                        b.WriteLine (format, arg0);
                        newline = true;
                }
-       
+
                public override void WriteLine (string format, params object [] args)
                {
                        OutputTabs ();
                        b.WriteLine (format, args);
                        newline = true;
                }
-               
+
                [CLSCompliant (false)]
                public override void WriteLine (uint value)
                {
@@ -689,21 +718,21 @@ namespace System.Web.UI {
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public override void WriteLine (string s)
                {
                        OutputTabs ();
                        b.WriteLine (s);
                        newline = true;
                }
-       
+
                public override void WriteLine (float value)
                {
                        OutputTabs ();
                        b.WriteLine (value);
                        newline = true;
                }
-       
+
                public void WriteLineNoTabs (string s)
                {
                        b.WriteLine (s);
@@ -712,7 +741,7 @@ namespace System.Web.UI {
 
                public override Encoding Encoding {
                        get {
-                               return b.Encoding;      
+                               return b.Encoding;
                        }
                }
 
@@ -725,16 +754,16 @@ namespace System.Web.UI {
                                indent = value;
                        }
                }
-       
+
                public System.IO.TextWriter InnerWriter {
                        get {
                                return b;
                        }
                        set {
                                b = value;
-                       }       
+                       }
                }
-       
+
                public override string NewLine {
                        get {
                                return b.NewLine;
@@ -743,7 +772,7 @@ namespace System.Web.UI {
                                b.NewLine = value;
                        }
                }
-       
+
                protected HtmlTextWriterTag TagKey {
                        get {
                                if (tagstack_pos == -1)
@@ -752,31 +781,59 @@ namespace System.Web.UI {
                                return tagstack [tagstack_pos].key;
                        }
                        set {
+#if TARGET_JVM
+                               if (tagstack [tagstack_pos] == null)
+                                       tagstack [tagstack_pos] = new AddedTag ();
+#endif
                                tagstack [tagstack_pos].key = value;
                                tagstack [tagstack_pos].name = GetTagName (value);
                        }
                }
-       
+
                protected string TagName {
                        get {
                                if (tagstack_pos == -1)
                                        throw new InvalidOperationException ();
-                               
+
                                return tagstack [tagstack_pos].name;
                        }
                        set {
+#if TARGET_JVM
+                               if (tagstack [tagstack_pos] == null)
+                                       tagstack [tagstack_pos] = new AddedTag ();
+#endif
                                tagstack [tagstack_pos].name = value;
                                tagstack [tagstack_pos].key = GetTagKey (value);
                                if (tagstack [tagstack_pos].key != HtmlTextWriterTag.Unknown)
                                        tagstack [tagstack_pos].name = GetTagName (tagstack [tagstack_pos].key);
                        }
                }
+
+               bool TagIgnore {
+                       get {
+                               if (tagstack_pos == -1)
+                                       throw new InvalidOperationException ();
+
+                               return tagstack [tagstack_pos].ignore;
+                       }
+
+                       set {
+                               if (tagstack_pos == -1)
+                                       throw new InvalidOperationException ();
+                               
+                               tagstack [tagstack_pos].ignore = value;
+                       }
+               }
                
+               internal HttpWriter GetHttpWriter ()
+               {
+                       return b as HttpWriter;
+               }
 
                TextWriter b;
                string tab_string;
                bool newline;
-               
+
                //
                // These emulate generic Stack <T>, since we can't use that ;-(. _pos is the current
                // element.IE, you edit blah [blah_pos]. I *really* want generics, sigh.
@@ -786,19 +843,35 @@ namespace System.Web.UI {
                AddedTag [] tagstack;
 
                int styles_pos = -1, attrs_pos = -1, tagstack_pos = -1;
-               
-               struct AddedTag {
+
+#if TARGET_JVM
+               class
+#else
+               struct 
+#endif
+               AddedTag {
                        public string name;
                        public HtmlTextWriterTag key;
+                       public bool ignore;
                }
-               
-               struct AddedStyle {
+
+#if TARGET_JVM
+               class
+#else
+               struct 
+#endif
+               AddedStyle {
                        public string name;
                        public HtmlTextWriterStyle key;
                        public string value;
                }
-               
-               struct AddedAttr {
+
+#if TARGET_JVM
+               class
+#else
+               struct 
+#endif
+               AddedAttr {
                        public string name;
                        public HtmlTextWriterAttribute key;
                        public string value;
@@ -808,10 +881,10 @@ namespace System.Web.UI {
                {
                        if (styles == null)
                                styles = new AddedStyle [16];
-                               
+
                        if (++styles_pos < styles.Length)
                                return;
-                       
+
                        int nsize = styles.Length * 2;
                        AddedStyle [] ncontents = new AddedStyle [nsize];
 
@@ -823,10 +896,10 @@ namespace System.Web.UI {
                {
                        if (attrs == null)
                                attrs = new AddedAttr [16];
-                               
+
                        if (++attrs_pos < attrs.Length)
                                return;
-                       
+
                        int nsize = attrs.Length * 2;
                        AddedAttr [] ncontents = new AddedAttr [nsize];
 
@@ -838,17 +911,17 @@ namespace System.Web.UI {
                {
                        if (tagstack == null)
                                tagstack = new AddedTag [16];
-                               
+
                        if (++tagstack_pos < tagstack.Length)
                                return;
-                                               
+
                        int nsize = tagstack.Length * 2;
                        AddedTag [] ncontents = new AddedTag [nsize];
 
                        Array.Copy (tagstack, ncontents, tagstack.Length);
                        tagstack = ncontents;
                }
-       
+
                public const string DefaultTabString = "\t";
                public const char DoubleQuoteChar = '"';
                public const string EndTagLeftChars = "</";
@@ -859,7 +932,7 @@ namespace System.Web.UI {
                public const char SemicolonChar = ';';
                public const char SingleQuoteChar = '\'';
                public const char SlashChar = '/';
-               public const char SpaceChar = ' ' ;
+               public const char SpaceChar = ' ';
                public const char StyleEqualsChar = ':';
                public const char TagLeftChar = '<';
                public const char TagRightChar = '>';
@@ -869,12 +942,12 @@ namespace System.Web.UI {
                        Inline,
                        SelfClosing,
                }
-               
-               
-               struct HtmlTag {
-                       public HtmlTextWriterTag key;
-                       public string name;
-                       public TagType tag_type;
+
+
+               sealed class HtmlTag {
+                       readonly public HtmlTextWriterTag key;
+                       readonly public string name;
+                       readonly public TagType tag_type;
 
                        public HtmlTag (HtmlTextWriterTag k, string n, TagType tt)
                        {
@@ -884,10 +957,10 @@ namespace System.Web.UI {
                        }
                }
 
-               struct HtmlStyle {
-                       public HtmlTextWriterStyle key;
-                       public string name;
-                       
+               sealed class HtmlStyle {
+                       readonly public HtmlTextWriterStyle key;
+                       readonly public string name;
+
                        public HtmlStyle (HtmlTextWriterStyle k, string n)
                        {
                                key = k;
@@ -895,10 +968,10 @@ namespace System.Web.UI {
                        }
                }
 
-               
-               struct HtmlAttribute {
-                       public HtmlTextWriterAttribute key;
-                       public string name;
+
+               sealed class HtmlAttribute {
+                       readonly public HtmlTextWriterAttribute key;
+                       readonly public string name;
 
                        public HtmlAttribute (HtmlTextWriterAttribute k, string n)
                        {
@@ -906,7 +979,7 @@ namespace System.Web.UI {
                                name = n;
                        }
                }
-               
+
                static HtmlTag [] tags = {
                        new HtmlTag (HtmlTextWriterTag.Unknown,    "",                  TagType.Block),
                        new HtmlTag (HtmlTextWriterTag.A,          "a",                 TagType.Inline),
@@ -1132,6 +1205,58 @@ namespace System.Web.UI {
                {
                        Write (HttpUtility.HtmlEncode (text));
                }
+
+               [MonoNotSupported ("")]
+               public virtual void WriteEncodedUrl (string url)
+               {
+                       // WriteUrlEncodedString (url, false);
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               public virtual void WriteEncodedUrlParameter (string urlText)
+               {
+                       // WriteUrlEncodedString (urlText, true);
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               protected void WriteUrlEncodedString (string text, bool argument)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               public virtual void EnterStyle (Style style)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               public virtual void EnterStyle (Style style, HtmlTextWriterTag tag)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               public virtual void ExitStyle (Style style)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoNotSupported ("")]
+               public virtual void ExitStyle (Style style, HtmlTextWriterTag tag)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               public virtual void BeginRender ()
+               {
+               }
+
+               public virtual void EndRender ()
+               {
+               }
 #endif
        }
 }