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