e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
1366 lines
44 KiB
C#
1366 lines
44 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="HtmlMobileTextWriter.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Web;
|
|
using System.Web.Mobile;
|
|
using System.Web.UI;
|
|
using System.Web.UI.MobileControls;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Security.Permissions;
|
|
|
|
#if COMPILING_FOR_SHIPPED_SOURCE
|
|
namespace System.Web.UI.MobileControls.ShippedAdapterSource
|
|
#else
|
|
namespace System.Web.UI.MobileControls.Adapters
|
|
#endif
|
|
|
|
{
|
|
|
|
/*
|
|
* HtmlMobileTextWriter class.
|
|
*/
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter"]/*' />
|
|
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
|
|
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
public class HtmlMobileTextWriter : MobileTextWriter
|
|
{
|
|
private bool _shouldEnsureStyle = true;
|
|
|
|
// mobile device type constants (should be defined somewhere else eventually)
|
|
internal WriterState _currentState;
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.HtmlMobileTextWriter"]/*' />
|
|
public HtmlMobileTextWriter(TextWriter writer, MobileCapabilities device)
|
|
: base(writer, device)
|
|
{
|
|
RenderBold = device.SupportsBold;
|
|
RenderItalic = device.SupportsItalic;
|
|
RenderFontSize = device.SupportsFontSize;
|
|
RenderFontName = device.SupportsFontName;
|
|
RenderFontColor = device.SupportsFontColor;
|
|
RenderBodyColor = device.SupportsBodyColor;
|
|
RenderDivAlign = device.SupportsDivAlign;
|
|
RenderDivNoWrap = device.SupportsDivNoWrap;
|
|
RequiresNoBreakInFormatting = device.RequiresNoBreakInFormatting;
|
|
_currentState = new WriterState(this);
|
|
}
|
|
|
|
/*
|
|
* the following TextWriter methods are overridden to
|
|
* first call EnsureStyle before delegating to the base
|
|
* class implementation
|
|
*/
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteBeginTag"]/*' />
|
|
public override void WriteBeginTag(String tag)
|
|
{
|
|
EnsureStyle();
|
|
base.WriteBeginTag(tag);
|
|
}
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteFullBeginTag"]/*' />
|
|
public override void WriteFullBeginTag(String tag)
|
|
{
|
|
EnsureStyle();
|
|
base.WriteFullBeginTag(tag);
|
|
}
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.Write"]/*' />
|
|
public override void Write(char c)
|
|
{
|
|
EnsureStyle();
|
|
base.Write(c);
|
|
}
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.Write1"]/*' />
|
|
public override void Write(String text)
|
|
{
|
|
EnsureStyle();
|
|
base.Write(text);
|
|
}
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteEncodedText"]/*' />
|
|
public override void WriteEncodedText(String text)
|
|
{
|
|
EnsureStyle();
|
|
if(Device["supportsCharacterEntityEncoding"] != "false") {
|
|
base.WriteEncodedText(text);
|
|
return;
|
|
}
|
|
if (null == text || text.Length == 0) {
|
|
return;
|
|
}
|
|
|
|
int length = text.Length;
|
|
int start = -1;
|
|
for(int pos = 0; pos < length; pos++) {
|
|
int ch = text[pos];
|
|
if(ch > 160 && ch < 256) {
|
|
if(start != -1) {
|
|
base.WriteEncodedText(text.Substring(start, pos - start));
|
|
start = -1;
|
|
}
|
|
base.Write(text[pos]);
|
|
}
|
|
else {
|
|
if(start == -1) {
|
|
start = pos;
|
|
}
|
|
}
|
|
}
|
|
if(start != -1) {
|
|
if(start == 0) {
|
|
base.WriteEncodedText(text);
|
|
}
|
|
else {
|
|
base.WriteEncodedText(text.Substring(start, length - start));
|
|
}
|
|
}
|
|
}
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteLine"]/*' />
|
|
public override void WriteLine(String text)
|
|
{
|
|
EnsureStyle();
|
|
base.WriteLine(text);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteBreak"]/*' />
|
|
public new void WriteBreak()
|
|
{
|
|
//Do not EnsureStyle for the break
|
|
base.WriteLine("<br>");
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.EnterLayout"]/*' />
|
|
public override void EnterLayout(Style style)
|
|
{
|
|
WriterStyle writerStyle = new WriterStyle(style);
|
|
writerStyle.Format = false;
|
|
EnterStyle(writerStyle);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitLayout"]/*' />
|
|
public override void ExitLayout(Style style, bool breakAfter)
|
|
{
|
|
ExitStyle(style, breakAfter);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitLayout1"]/*' />
|
|
public override void ExitLayout(Style style)
|
|
{
|
|
ExitStyle(style, false);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.MarkStyleContext"]/*' />
|
|
protected internal void MarkStyleContext()
|
|
{
|
|
_shouldEnsureStyle = true;
|
|
_currentState.MarkStyleContext();
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.UnMarkStyleContext"]/*' />
|
|
protected internal void UnMarkStyleContext()
|
|
{
|
|
_shouldEnsureStyle = true;
|
|
_currentState.UnMarkStyleContext();
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.EnterFormat"]/*' />
|
|
public override void EnterFormat(Style style)
|
|
{
|
|
WriterStyle writerStyle = new WriterStyle(style);
|
|
writerStyle.Layout = false;
|
|
EnterStyle(writerStyle);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitFormat"]/*' />
|
|
public override void ExitFormat(Style style)
|
|
{
|
|
ExitStyle(style);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitFormat1"]/*' />
|
|
public override void ExitFormat(Style style, bool breakAfter)
|
|
{
|
|
ExitStyle(style, breakAfter);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.BeginStyleContext"]/*' />
|
|
public void BeginStyleContext()
|
|
{
|
|
if(_currentState.BreakPending)
|
|
{
|
|
WriteBreak();
|
|
_currentState.BreakPending = false;
|
|
}
|
|
_currentState.PushState();
|
|
EnterStyle(new WriterStyle());
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.EndStyleContext"]/*' />
|
|
public void EndStyleContext()
|
|
{
|
|
if(_currentState.BreakPending)
|
|
{
|
|
WriteBreak();
|
|
_currentState.BreakPending = false;
|
|
}
|
|
_currentState.PopState();
|
|
_currentState.Pop();
|
|
_currentState.Transition(new WriterStyle());
|
|
}
|
|
|
|
/* all calls to Enter... converge to this */
|
|
private void EnterStyle(WriterStyle style)
|
|
{
|
|
_currentState.Push(style);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.EnterStyle"]/*' />
|
|
public new void EnterStyle(Style style)
|
|
{
|
|
EnterStyle(new WriterStyle(style));
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitStyle"]/*' />
|
|
public new void ExitStyle(Style style)
|
|
{
|
|
ExitStyle(style, false);
|
|
|
|
}
|
|
|
|
internal bool ShouldEnsureStyle
|
|
{
|
|
get
|
|
{
|
|
return _shouldEnsureStyle;
|
|
}
|
|
set
|
|
{
|
|
_shouldEnsureStyle = value;
|
|
}
|
|
}
|
|
|
|
/*
|
|
all calls to Exit... converge to this
|
|
*/
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.ExitStyle1"]/*' />
|
|
public void ExitStyle(Style style, bool breakAfter)
|
|
{
|
|
_currentState.Pop();
|
|
if((_currentState.BreakPending) && (_currentState.Count > 0))
|
|
{
|
|
EnsureStyle();
|
|
}
|
|
_currentState.BreakPending = breakAfter;
|
|
if((_currentState.Count == 0) || (RequiresNoBreakInFormatting))
|
|
{
|
|
_currentState.Transition(new WriterStyle());
|
|
}
|
|
InputWritten = false;
|
|
}
|
|
|
|
internal bool _inputWritten = false;
|
|
internal bool InputWritten
|
|
{
|
|
get { return _inputWritten; }
|
|
set { _inputWritten = value; }
|
|
}
|
|
|
|
internal void EnsureStyle()
|
|
{
|
|
if (_shouldEnsureStyle)
|
|
{
|
|
if(_currentState.Count > 0)
|
|
{
|
|
_currentState.Transition(_currentState.Peek());
|
|
}
|
|
_shouldEnsureStyle = false;
|
|
}
|
|
if(BeforeFirstControlWritten)
|
|
{
|
|
BeforeFirstControlWritten = false;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteText"]/*' />
|
|
public void WriteText(String text, bool encodeText)
|
|
{
|
|
if(text != null && text.Length == 0)
|
|
{
|
|
return;
|
|
}
|
|
EnsureStyle();
|
|
if (encodeText)
|
|
{
|
|
WriteEncodedText(text);
|
|
}
|
|
else
|
|
{
|
|
Write(text);
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteUrlParameter"]/*' />
|
|
public void WriteUrlParameter(String name, String value)
|
|
{
|
|
WriteEncodedUrlParameter(name);
|
|
Write("=");
|
|
WriteEncodedUrlParameter(value);
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.WriteHiddenField"]/*' />
|
|
public void WriteHiddenField(String name, String value)
|
|
{
|
|
WriteBeginTag("input");
|
|
WriteAttribute("type", "hidden");
|
|
WriteAttribute("name", name);
|
|
WriteAttribute("value", value, true);
|
|
Write(">\r\n");
|
|
}
|
|
|
|
|
|
// AUI 2285
|
|
private bool _beforeFirstControlWritten = true;
|
|
internal bool BeforeFirstControlWritten
|
|
{
|
|
get
|
|
{
|
|
return _beforeFirstControlWritten;
|
|
}
|
|
|
|
set
|
|
{
|
|
_beforeFirstControlWritten = value;
|
|
}
|
|
}
|
|
|
|
private bool _maintainState = true;
|
|
|
|
internal bool MaintainState
|
|
{
|
|
get
|
|
{
|
|
return _maintainState;
|
|
}
|
|
set
|
|
{
|
|
_maintainState = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderBold"]/*' />
|
|
protected internal bool RenderBold
|
|
{
|
|
get
|
|
{
|
|
return _renderBold;
|
|
}
|
|
set
|
|
{
|
|
_renderBold = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderItalic"]/*' />
|
|
protected internal bool RenderItalic
|
|
{
|
|
get
|
|
{
|
|
return _renderItalic;
|
|
}
|
|
set
|
|
{
|
|
_renderItalic = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderFontSize"]/*' />
|
|
protected internal bool RenderFontSize
|
|
{
|
|
get
|
|
{
|
|
return _renderFontSize;
|
|
}
|
|
set
|
|
{
|
|
_renderFontSize = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderFontName"]/*' />
|
|
protected internal bool RenderFontName
|
|
{
|
|
get
|
|
{
|
|
return _renderFontName;
|
|
}
|
|
|
|
set
|
|
{
|
|
_renderFontName = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderFontColor"]/*' />
|
|
protected internal bool RenderFontColor
|
|
{
|
|
get
|
|
{
|
|
return _renderFontColor;
|
|
}
|
|
set
|
|
{
|
|
_renderFontColor = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderBodyColor"]/*' />
|
|
protected internal bool RenderBodyColor
|
|
{
|
|
get
|
|
{
|
|
return _renderBodyColor;
|
|
}
|
|
set
|
|
{
|
|
_renderBodyColor = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderDivAlign"]/*' />
|
|
protected internal bool RenderDivAlign
|
|
{
|
|
get
|
|
{
|
|
return _renderDivAlign;
|
|
}
|
|
set
|
|
{
|
|
_renderDivAlign = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RenderDivNoWrap"]/*' />
|
|
protected internal bool RenderDivNoWrap
|
|
{
|
|
get
|
|
{
|
|
return _renderDivNoWrap;
|
|
}
|
|
set
|
|
{
|
|
_renderDivNoWrap = value;
|
|
}
|
|
}
|
|
|
|
/// <include file='doc\HtmlMobileTextWriter.uex' path='docs/doc[@for="HtmlMobileTextWriter.RequiresNoBreakInFormatting"]/*' />
|
|
protected internal bool RequiresNoBreakInFormatting
|
|
{
|
|
get
|
|
{
|
|
return _requiresNoBreakInFormatting;
|
|
}
|
|
set
|
|
{
|
|
_requiresNoBreakInFormatting = value;
|
|
}
|
|
}
|
|
|
|
private bool _renderBold = true;
|
|
private bool _renderItalic = true;
|
|
private bool _renderFontSize = true;
|
|
private bool _renderFontName = true;
|
|
private bool _renderFontColor = true;
|
|
private bool _renderBodyColor = true;
|
|
private bool _renderDivAlign = true;
|
|
private bool _renderDivNoWrap = false;
|
|
private bool _requiresNoBreakInFormatting = false;
|
|
}
|
|
|
|
/*
|
|
* the WriterStyle class is used to store and
|
|
* control state for rendering format and layout
|
|
*/
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class WriterStyle
|
|
{
|
|
private Wrapping _wrapping;
|
|
private Alignment _alignment;
|
|
private String _fontName;
|
|
private Color _fontColor;
|
|
private FontSize _fontSize;
|
|
private bool _bold;
|
|
private bool _italic;
|
|
|
|
private bool _format;
|
|
private bool _layout;
|
|
|
|
internal WriterStyle()
|
|
{
|
|
_wrapping = Wrapping.Wrap;
|
|
_alignment = Alignment.Left;
|
|
_fontName = String.Empty;
|
|
_fontColor = Color.Empty;
|
|
_fontSize = FontSize.Normal;
|
|
_bold = false;
|
|
_italic = false;
|
|
|
|
_format = true;
|
|
_layout = true;
|
|
}
|
|
|
|
internal WriterStyle(Style style)
|
|
{
|
|
Debug.Assert(style != null, "writer style is null");
|
|
_alignment = (Alignment) style[Style.AlignmentKey, true];
|
|
if(_alignment == Alignment.NotSet)
|
|
{
|
|
_alignment = Alignment.Left;
|
|
}
|
|
_wrapping = (Wrapping) style[Style.WrappingKey, true];
|
|
if(_wrapping == Wrapping.NotSet)
|
|
{
|
|
_wrapping = Wrapping.Wrap;
|
|
}
|
|
|
|
_fontSize = (FontSize) style[Style.FontSizeKey , true];
|
|
if(_fontSize == FontSize.NotSet)
|
|
{
|
|
_fontSize = FontSize.Normal;
|
|
}
|
|
_fontName = (String) style[Style.FontNameKey , true];
|
|
_fontColor = (Color) style[Style.ForeColorKey, true];
|
|
|
|
_bold = ((BooleanOption) style[Style.BoldKey, true] == BooleanOption.True);
|
|
_italic = ((BooleanOption) style[Style.ItalicKey, true] == BooleanOption.True);
|
|
|
|
_format = true;
|
|
_layout = true;
|
|
|
|
}
|
|
|
|
|
|
internal bool Format
|
|
{
|
|
get { return _format; }
|
|
set { _format = value; }
|
|
}
|
|
|
|
internal bool Layout
|
|
{
|
|
get { return _layout; }
|
|
set { _layout = value; }
|
|
}
|
|
|
|
internal Wrapping Wrapping
|
|
{
|
|
get { return _wrapping; }
|
|
set { _wrapping = value; }
|
|
}
|
|
internal Alignment Alignment
|
|
{
|
|
get { return _alignment; }
|
|
set { _alignment = value; }
|
|
}
|
|
internal String FontName
|
|
{
|
|
get { return _fontName; }
|
|
set { _fontName = value; }
|
|
}
|
|
internal Color FontColor
|
|
{
|
|
get { return _fontColor; }
|
|
set { _fontColor = value; }
|
|
}
|
|
internal FontSize FontSize
|
|
{
|
|
get { return _fontSize; }
|
|
set { _fontSize = value; }
|
|
}
|
|
internal bool Bold
|
|
{
|
|
get { return _bold; }
|
|
set { _bold = value; }
|
|
}
|
|
internal bool Italic
|
|
{
|
|
get { return _italic; }
|
|
set { _italic = value; }
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The StyleTag class is extended for specific tags
|
|
*/
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal abstract class StyleTag
|
|
{
|
|
private int _level = -1;
|
|
|
|
#if UNUSED_CODE
|
|
internal StyleTag()
|
|
{
|
|
}
|
|
#endif
|
|
|
|
internal StyleTag(int level)
|
|
{
|
|
_level = level;
|
|
}
|
|
|
|
internal virtual int Level
|
|
{
|
|
get
|
|
{
|
|
return _level;
|
|
}
|
|
set
|
|
{
|
|
_level = value;
|
|
}
|
|
}
|
|
|
|
internal abstract void CloseTag(WriterState state);
|
|
}
|
|
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class BoldStyleTag : StyleTag
|
|
{
|
|
internal BoldStyleTag(int level) : base(level)
|
|
{
|
|
}
|
|
|
|
internal override void CloseTag(WriterState state)
|
|
{
|
|
state.Writer.WriteEndTag("b");
|
|
state.Current.Bold = false;
|
|
}
|
|
}
|
|
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class ItalicStyleTag : StyleTag
|
|
{
|
|
internal ItalicStyleTag(int level) : base(level)
|
|
{
|
|
}
|
|
|
|
internal override void CloseTag(WriterState state)
|
|
{
|
|
state.Writer.WriteEndTag("i");
|
|
state.Current.Italic = false;
|
|
}
|
|
}
|
|
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class FontStyleTag : StyleTag
|
|
{
|
|
private String _name;
|
|
private Color _color;
|
|
private FontSize _size;
|
|
|
|
internal FontStyleTag(int level) : base(level)
|
|
{
|
|
_name = String.Empty;
|
|
_color = Color.Empty;
|
|
_size = FontSize.Normal;
|
|
}
|
|
|
|
#if UNUSED_CODE
|
|
internal FontStyleTag(int level, String name, Color color, FontSize size) : base(level)
|
|
{
|
|
Name = _name;
|
|
Color = color;
|
|
FontSize = size;
|
|
}
|
|
#endif
|
|
|
|
internal String Name
|
|
{
|
|
get { return _name; }
|
|
set { _name = value; }
|
|
}
|
|
internal Color Color
|
|
{
|
|
get { return _color; }
|
|
set { _color = value; }
|
|
}
|
|
internal FontSize FontSize
|
|
{
|
|
get { return _size; }
|
|
set { _size = value; }
|
|
}
|
|
|
|
internal override void CloseTag(WriterState state)
|
|
{
|
|
state.Writer.WriteEndTag("font");
|
|
//reset FontLevel and rebuild state info
|
|
state.FontLevel = -1;
|
|
state.Current.FontColor = Color.Empty;
|
|
state.Current.FontName = String.Empty;
|
|
state.Current.FontSize = FontSize.Normal;
|
|
|
|
//reset the FontLevel
|
|
Stack tmpStack = new Stack();
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tmpStack.Push(o);
|
|
if(o is FontStyleTag)
|
|
{
|
|
state.FontLevel = ((FontStyleTag)o).Level;
|
|
break;
|
|
}
|
|
}
|
|
|
|
while(tmpStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tmpStack.Pop());
|
|
}
|
|
|
|
//there is a font tag in the stack
|
|
if(state.FontLevel > -1)
|
|
{
|
|
if(Color != Color.Empty)
|
|
{
|
|
//reset font color to something further down the stack
|
|
Stack tempStack = new Stack();
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tempStack.Push(o);
|
|
if(o is FontStyleTag)
|
|
{
|
|
if(((FontStyleTag)o).Color != Color.Empty)
|
|
{
|
|
state.Current.FontColor = ((FontStyleTag)o).Color;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while(tempStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tempStack.Pop());
|
|
}
|
|
}
|
|
if(Name == null || Name.Length > 0)
|
|
{
|
|
//reset font name to something futher down the stack
|
|
Stack tempStack = new Stack();
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tempStack.Push(o);
|
|
if(o is FontStyleTag)
|
|
{
|
|
String name = ((FontStyleTag)o).Name;
|
|
if(name == null || name.Length > 0)
|
|
{
|
|
state.Current.FontName = name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while(tempStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tempStack.Pop());
|
|
}
|
|
}
|
|
//reset font size to something further down the stack
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tmpStack.Push(o);
|
|
if (o is FontStyleTag)
|
|
{
|
|
if(((FontStyleTag)o).FontSize != FontSize.Normal)
|
|
{
|
|
state.Current.FontSize = ((FontStyleTag)o).FontSize;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while(tmpStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tmpStack.Pop());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class DivStyleTag : StyleTag
|
|
{
|
|
private Wrapping _wrapping;
|
|
private Alignment _alignment;
|
|
private bool _alignWritten;
|
|
internal DivStyleTag(int level) : base(level)
|
|
{
|
|
_wrapping = Wrapping.Wrap;
|
|
_alignment = Alignment.Left;
|
|
_alignWritten = false;
|
|
}
|
|
|
|
internal Wrapping Wrapping
|
|
{
|
|
get { return _wrapping; }
|
|
set { _wrapping = value; }
|
|
}
|
|
internal Alignment Alignment
|
|
{
|
|
get { return _alignment; }
|
|
set { _alignment = value; }
|
|
}
|
|
internal bool AlignmentWritten
|
|
{
|
|
get { return _alignWritten; }
|
|
set { _alignWritten = value; }
|
|
}
|
|
|
|
internal override void CloseTag(WriterState state)
|
|
{
|
|
state.Writer.WriteEndTag("div");
|
|
state.BreakPending = false;
|
|
|
|
//reset current div info and rebuild
|
|
state.DivLevel = -1;
|
|
state.Current.Alignment = Alignment.Left;
|
|
state.Current.Wrapping = Wrapping.Wrap;
|
|
Stack tempStack = new Stack();
|
|
//reset alignment : ideally these resets could be combined
|
|
//in practice, the number of items on the stack is small
|
|
//so it may be comparable
|
|
|
|
|
|
//reset wrapping
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tempStack.Push(o);
|
|
if(o is DivStyleTag)
|
|
{
|
|
if(((DivStyleTag)o).Wrapping == Wrapping.NoWrap)
|
|
{
|
|
state.Current.Wrapping = Wrapping.NoWrap;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while(tempStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tempStack.Pop());
|
|
}
|
|
|
|
//reset alignment
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tempStack.Push(o);
|
|
if(o is DivStyleTag)
|
|
{
|
|
if(((DivStyleTag)o).Alignment != Alignment.NotSet)
|
|
{
|
|
state.Current.Alignment = ((DivStyleTag)o).Alignment;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while(tempStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tempStack.Pop());
|
|
}
|
|
|
|
//reset divLevel
|
|
while(state.TagsWritten.Count > 0)
|
|
{
|
|
Object o = state.TagsWritten.Pop();
|
|
tempStack.Push(o);
|
|
if(o is DivStyleTag)
|
|
{
|
|
state.DivLevel = ((DivStyleTag)o).Level;
|
|
break;
|
|
}
|
|
}
|
|
while(tempStack.Count > 0)
|
|
{
|
|
state.TagsWritten.Push(tempStack.Pop());
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* the StyleStack class maintains WriterStyle objects
|
|
* pushed on the stack from Enter[Style/Format/Layout]
|
|
* and removed using Exit[Style/Format/Layout]
|
|
*/
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class StyleStack
|
|
{
|
|
private HtmlMobileTextWriter _writer;
|
|
private Stack _stack;
|
|
|
|
protected StyleStack(HtmlMobileTextWriter writer)
|
|
{
|
|
_writer = writer;
|
|
_stack = new Stack();
|
|
}
|
|
|
|
internal void Push(WriterStyle style)
|
|
{
|
|
_stack.Push(style);
|
|
_writer.ShouldEnsureStyle = true;
|
|
}
|
|
|
|
internal WriterStyle Pop()
|
|
{
|
|
_writer.ShouldEnsureStyle = true;
|
|
return (WriterStyle)_stack.Pop();
|
|
}
|
|
|
|
internal WriterStyle Peek()
|
|
{
|
|
if(_stack.Count == 0)
|
|
{
|
|
return new WriterStyle(); //retrieves default values
|
|
}
|
|
return (WriterStyle)_stack.Peek();
|
|
}
|
|
|
|
internal int Count
|
|
{
|
|
get
|
|
{
|
|
return _stack.Count;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* the WriterState tracks what styles have been entered, what tags have been written
|
|
and controls transitions from the current state to a desired state
|
|
*/
|
|
[Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
|
|
internal class WriterState : StyleStack
|
|
{
|
|
private bool _inTransition = false; //prevent recursion
|
|
private Stack _stack; //stack of WriterStyle objects
|
|
private Stack _tagsWritten; //stack of StyleTag objects for written tags
|
|
private bool _breakPending = false; //track if we owe a <br>
|
|
|
|
private WriterStyle _current; //the current style
|
|
private HtmlMobileTextWriter _writer; //the output stream
|
|
|
|
private int _fontLevel = -1;
|
|
private int _divLevel = -1;
|
|
|
|
private int _mark = 0;
|
|
|
|
internal WriterState(HtmlMobileTextWriter writer) : base(writer)
|
|
{
|
|
_writer = writer;
|
|
_stack = new Stack();
|
|
_current = new WriterStyle();
|
|
_tagsWritten = new Stack();
|
|
}
|
|
|
|
internal WriterStyle Current
|
|
{
|
|
get
|
|
{
|
|
return _current;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Pushes the current WriterStyle and tagsWritten stack for later use,
|
|
starts using a new default WriterStyle
|
|
*/
|
|
internal void PushState()
|
|
{
|
|
_writer.ShouldEnsureStyle = true;
|
|
_stack.Push(_current);
|
|
_current = new WriterStyle();
|
|
_stack.Push(_tagsWritten);
|
|
_tagsWritten = new Stack();
|
|
_stack.Push(BreakPending);
|
|
BreakPending = false;
|
|
|
|
}
|
|
|
|
internal int FontLevel
|
|
{
|
|
get { return _fontLevel; }
|
|
set { _fontLevel = value; }
|
|
}
|
|
|
|
internal int DivLevel
|
|
{
|
|
get { return _divLevel; }
|
|
set { _divLevel = value; }
|
|
}
|
|
|
|
/*
|
|
Pops the last WriterStyle pushed and makes it current
|
|
and restores the tagsWritten stack
|
|
*/
|
|
internal WriterStyle PopState()
|
|
{
|
|
_writer.ShouldEnsureStyle = true;
|
|
BreakPending = (bool)_stack.Pop();
|
|
//close all open tags
|
|
while(_tagsWritten.Count > 0)
|
|
{
|
|
CloseTag();
|
|
}
|
|
_tagsWritten = (Stack)_stack.Pop();
|
|
_current = (WriterStyle)_stack.Pop();
|
|
return _current;
|
|
}
|
|
|
|
/*
|
|
BreakPending property accessor
|
|
*/
|
|
internal bool BreakPending
|
|
{
|
|
get { return _breakPending; }
|
|
set { _breakPending = value; }
|
|
}
|
|
|
|
internal HtmlTextWriter Writer
|
|
{
|
|
get
|
|
{
|
|
return _writer;
|
|
}
|
|
}
|
|
|
|
internal Stack TagsWritten
|
|
{
|
|
get
|
|
{
|
|
return _tagsWritten;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
pop a tag from the stack of StyleTags,
|
|
adjust state accordingly
|
|
*/
|
|
internal void CloseTag()
|
|
{
|
|
StyleTag tag = (StyleTag)_tagsWritten.Pop();
|
|
tag.CloseTag(this);
|
|
}
|
|
|
|
internal void MarkStyleContext()
|
|
{
|
|
_mark = _tagsWritten.Count;
|
|
}
|
|
|
|
internal void UnMarkStyleContext()
|
|
{
|
|
while(_tagsWritten.Count > _mark)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
private bool FontChange(WriterStyle newStyle)
|
|
{
|
|
return (
|
|
(( _current.FontColor != newStyle.FontColor ) && (_writer.RenderFontColor)) ||
|
|
(( _current.FontSize != newStyle.FontSize ) && (_writer.RenderFontSize)) ||
|
|
(( _current.FontName != newStyle.FontName ) && (_writer.RenderFontName))
|
|
);
|
|
}
|
|
|
|
private bool DivChange(WriterStyle newStyle)
|
|
{
|
|
return (
|
|
(newStyle.Layout) &&
|
|
(((newStyle.Wrapping != _current.Wrapping) && (_writer.RenderDivNoWrap)) ||
|
|
((newStyle.Alignment != _current.Alignment) && (_writer.RenderDivAlign)) )
|
|
);
|
|
}
|
|
|
|
internal void Transition(WriterStyle newStyle)
|
|
{
|
|
Transition(newStyle, true);
|
|
}
|
|
|
|
private const String _pocketPC = "Pocket IE";
|
|
|
|
internal void Transition(WriterStyle newStyle, bool captureOutput)
|
|
{
|
|
HtmlMobileTextWriter tempWriter = _writer;
|
|
try
|
|
{
|
|
if(!captureOutput)
|
|
{
|
|
tempWriter = _writer;
|
|
_writer = new HtmlMobileTextWriter(
|
|
new HtmlTextWriter(new StringWriter(CultureInfo.InvariantCulture)), tempWriter.Device);
|
|
}
|
|
|
|
if(_inTransition)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
_inTransition = true;
|
|
}
|
|
|
|
if(Count == 0)
|
|
{
|
|
while(_tagsWritten.Count > 0)
|
|
{
|
|
CloseTag();
|
|
}
|
|
_inTransition= false;
|
|
return;
|
|
}
|
|
|
|
//close italic if target format !italic
|
|
if(( _current.Italic && !newStyle.Italic ) && (_writer.RenderItalic))
|
|
{
|
|
while(_current.Italic)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//close bold if target format !bold
|
|
if(( _current.Bold && !newStyle.Bold ) && (_writer.RenderBold))
|
|
{
|
|
while(_current.Bold)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//if the target FontColor is Color.Empty, then we need to
|
|
//close all open color tags
|
|
if(
|
|
(newStyle.FontColor == Color.Empty) &&
|
|
(_current.FontColor != Color.Empty) &&
|
|
(_writer.RenderFontColor) )
|
|
{
|
|
while(_current.FontColor != Color.Empty)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//if the target FontName is String.Empty, then we need to
|
|
//close all open name tags
|
|
if(
|
|
(newStyle.FontName != null && newStyle.FontName.Length == 0) &&
|
|
(_current.FontName == null || _current.FontName.Length > 0) &&
|
|
(_writer.RenderFontName) )
|
|
{
|
|
while(_current.FontName == null || _current.FontName.Length > 0)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//close the font if it is of the same or a later generation
|
|
//and differs
|
|
|
|
bool newFont = FontChange(newStyle);
|
|
|
|
if(newFont)
|
|
{
|
|
while( FontLevel >= Count )
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//if the new wrapping is Wrap, and the current is NoWrap
|
|
//the outer NoWrap must be removed
|
|
if(
|
|
(newStyle.Wrapping == Wrapping.Wrap) &&
|
|
(_current.Wrapping == Wrapping.NoWrap) &&
|
|
(_writer.RenderDivNoWrap) )
|
|
{
|
|
while(_current.Wrapping != Wrapping.Wrap)
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
//if the alignment differs for the same generation, close any divs at this level
|
|
if(( newStyle.Alignment != _current.Alignment ) && ( _writer.RenderDivAlign))
|
|
{
|
|
while( DivLevel >= Count )
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
//determine if we will be opening a div before writing any break
|
|
bool newDiv = DivChange(newStyle);
|
|
|
|
//an opening div will function as a logical break
|
|
if((BreakPending) && (!(newDiv)))
|
|
{
|
|
((HtmlMobileTextWriter)_writer).WriteBreak();
|
|
BreakPending = false;
|
|
}
|
|
|
|
if(newDiv)
|
|
{
|
|
while(_current.Bold || _current.Italic || (FontLevel == Count))
|
|
{
|
|
CloseTag();
|
|
}
|
|
}
|
|
|
|
newFont = FontChange(newStyle);
|
|
newDiv = DivChange(newStyle);
|
|
|
|
//open div
|
|
if(newDiv && newStyle.Layout)
|
|
{
|
|
DivStyleTag div = new DivStyleTag(Count);
|
|
BreakPending = false;
|
|
if(
|
|
((_writer.BeforeFirstControlWritten) || (_writer.InputWritten)) &&
|
|
(_writer.Device.Type == _pocketPC) &&
|
|
(_writer.Device.MinorVersion == 0) &&
|
|
(_writer.Device.MajorVersion == 4) &&
|
|
(newStyle.Alignment != _current.Alignment) )
|
|
{
|
|
_writer.WriteBreak();
|
|
_writer.InputWritten = false;
|
|
}
|
|
|
|
|
|
_writer.WriteBeginTag("div");
|
|
DivLevel = Count;
|
|
|
|
if(newStyle.Wrapping == Wrapping.NoWrap)
|
|
{
|
|
if(_writer.RenderDivNoWrap)
|
|
{
|
|
_writer.Write(" nowrap");
|
|
}
|
|
div.Wrapping = Wrapping.NoWrap;
|
|
_current.Wrapping = Wrapping.NoWrap;
|
|
}
|
|
else
|
|
{
|
|
div.Wrapping = Wrapping.Wrap;
|
|
_current.Wrapping = Wrapping.Wrap;
|
|
}
|
|
|
|
if(newStyle.Alignment != _current.Alignment)
|
|
{
|
|
if(_writer.RenderDivAlign)
|
|
{
|
|
_writer.WriteAttribute(
|
|
"align",
|
|
Enum.GetName(typeof(Alignment), newStyle.Alignment));
|
|
}
|
|
_current.Alignment = newStyle.Alignment;
|
|
div.Alignment = newStyle.Alignment;
|
|
div.AlignmentWritten = true;
|
|
}
|
|
_tagsWritten.Push(div);
|
|
_writer.Write(">");
|
|
}
|
|
|
|
//open font
|
|
if(newFont && newStyle.Format)
|
|
{
|
|
FontStyleTag fontTag = new FontStyleTag(Count);
|
|
_writer.WriteBeginTag("font");
|
|
if(_current.FontSize != newStyle.FontSize)
|
|
{
|
|
String relativeSize;
|
|
if(newStyle.FontSize == FontSize.Large)
|
|
{
|
|
relativeSize = (
|
|
((HtmlMobileTextWriter)_writer).Device.Type == _pocketPC) ? "+2" : "+1";
|
|
_current.FontSize = FontSize.Large;
|
|
fontTag.FontSize = FontSize.Large;
|
|
}
|
|
else if(newStyle.FontSize == FontSize.Small)
|
|
{
|
|
relativeSize = "-1";
|
|
_current.FontSize = FontSize.Small;
|
|
fontTag.FontSize = FontSize.Small;
|
|
}
|
|
else //(newStyle.FontSize == FontSize.Normal)
|
|
{
|
|
relativeSize = "+0";
|
|
_current.FontSize = FontSize.Normal;
|
|
fontTag.FontSize = FontSize.Normal;
|
|
}
|
|
if(_writer.RenderFontSize)
|
|
{
|
|
_writer.WriteAttribute("size", relativeSize);
|
|
}
|
|
}
|
|
|
|
if(_current.FontColor != newStyle.FontColor)
|
|
{
|
|
if(_writer.RenderFontColor)
|
|
{
|
|
_writer.WriteAttribute(
|
|
"color",
|
|
ColorTranslator.ToHtml(newStyle.FontColor));
|
|
}
|
|
_current.FontColor = newStyle.FontColor;
|
|
fontTag.Color = newStyle.FontColor;
|
|
}
|
|
if(_current.FontName != newStyle.FontName)
|
|
{
|
|
if(_writer.RenderFontName)
|
|
{
|
|
_writer.WriteAttribute("face", newStyle.FontName);
|
|
}
|
|
_current.FontName = newStyle.FontName;
|
|
fontTag.Name = newStyle.FontName;
|
|
}
|
|
_writer.Write(">");
|
|
_tagsWritten.Push(fontTag);
|
|
FontLevel = Count;
|
|
}
|
|
|
|
//open bold
|
|
if(newStyle.Format)
|
|
{
|
|
if( newStyle.Bold && !_current.Bold && _writer.RenderBold )
|
|
{
|
|
_writer.WriteFullBeginTag("b");
|
|
_current.Bold = true;
|
|
_tagsWritten.Push(new BoldStyleTag(Count));
|
|
}
|
|
|
|
//open italic
|
|
if( newStyle.Italic && !_current.Italic && _writer.RenderItalic )
|
|
{
|
|
_writer.WriteFullBeginTag("i");
|
|
_current.Italic = true;
|
|
_tagsWritten.Push(new ItalicStyleTag(Count));
|
|
}
|
|
}
|
|
_inTransition = false;
|
|
}
|
|
finally
|
|
{
|
|
_writer = tempWriter;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|