////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package flashx.textLayout.conversion 
{
	import flash.system.System;
	import flash.text.engine.Kerning;
	import flash.utils.Dictionary;
	
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.BreakElement;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.DivElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowGroupElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.IConfiguration;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.ListElement;
	import flashx.textLayout.elements.ListItemElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.SubParagraphGroupElement;
	import flashx.textLayout.elements.SubParagraphGroupElementBase;
	import flashx.textLayout.elements.TabElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.Float;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.LeadingModel;
	import flashx.textLayout.formats.ListMarkerFormat;
	import flashx.textLayout.formats.ListStyleType;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.property.Property;
	import flashx.textLayout.tlf_internal;

	use namespace tlf_internal;
	
	[ExcludeClass]
	/** 
	 * @private
	 * TextFieldHtmlImporter converts from HTML to TextLayout data structures
	 */ 	
	public class TextFieldHtmlImporter extends BaseTextLayoutImporter implements IHTMLImporter
	{	
		// TLF formats to which <font/> attributes map directly
		/** @private */
		static tlf_internal const _fontDescription:Object = {
			color:TextLayoutFormat.colorProperty,
			trackingRight:TextLayoutFormat.trackingRightProperty,
			fontFamily:TextLayoutFormat.fontFamilyProperty
		};
		
		// <font/> attributes that require custom logic for mapping to TLF formats
		/** @private */
		static tlf_internal const _fontMiscDescription:Object = {
			size	: Property.NewStringProperty("size", null, false, null),
			kerning	: Property.NewStringProperty("kerning", null, false, null)
		};
				
		// TLF formats to which <textformat/> attributes map directly		
		/** @private */
		static tlf_internal const _textFormatDescription:Object = {
			paragraphStartIndent:TextLayoutFormat.paragraphStartIndentProperty,
			paragraphEndIndent:TextLayoutFormat.paragraphEndIndentProperty,
			textIndent:TextLayoutFormat.textIndentProperty,
			lineHeight:TextLayoutFormat.lineHeightProperty,
			tabStops:TextLayoutFormat.tabStopsProperty
		};	
		
		// <textformat/> attributes that require custom logic for mapping to TLF formats
		/** @private */
		static tlf_internal const _textFormatMiscDescription:Object = {
			blockIndent	: Property.NewStringProperty("blockIndent", null, false, null)
		};
		
		/** @private */
		static tlf_internal const _paragraphFormatDescription:Object = {
			textAlign:TextLayoutFormat.textAlignProperty
		};
		
		/** @private */
		static tlf_internal const _linkHrefDescription:Object = {
			href	: Property.NewStringProperty("href",   null, false, null)
		};
		
		/** @private */
		static tlf_internal const _linkTargetDescription:Object = {
			target	: Property.NewStringProperty("target", null, false, null)
		};
		
		/** @private */
		static tlf_internal const _imageDescription:Object = {
			height	: InlineGraphicElement.heightPropertyDefinition,
			width	: InlineGraphicElement.widthPropertyDefinition
		};
		
		// Separate description because id value is case-sensitive unlike others
		/** @private */
		static tlf_internal const _imageMiscDescription:Object = {
			src		: Property.NewStringProperty("src", null, false, null),
			align	: Property.NewStringProperty("align", null, false, null)
		};
			
		/** @private Finish defining at run time because it has a member variable "CLASS" which is a reserved keyword. */
		static tlf_internal const _classAndIdDescription:Object = { 
			id		: Property.NewStringProperty("ID", null, false, null)
		};
		
		// For some reason, the following can't be initialized here
		/** @private */
		static tlf_internal var _fontImporter:FontImporter;
		/** @private */
		static tlf_internal var _fontMiscImporter:CaseInsensitiveTLFFormatImporter;
		/** @private */
		static tlf_internal var _textFormatImporter:TextFormatImporter;
		/** @private */
		static tlf_internal var _textFormatMiscImporter:CaseInsensitiveTLFFormatImporter;		
		/** @private */
		static tlf_internal var _paragraphFormatImporter:HtmlCustomParaFormatImporter;
		/** @private */
		static tlf_internal var _linkHrefImporter:CaseInsensitiveTLFFormatImporter;
		/** @private */
		static tlf_internal var _linkTargetImporter:CaseInsensitiveTLFFormatImporter;
		/** @private */
		static tlf_internal var _ilgFormatImporter:CaseInsensitiveTLFFormatImporter;
		/** @private */
		static tlf_internal var _ilgMiscFormatImporter:CaseInsensitiveTLFFormatImporter;
		/** @private */
		static tlf_internal var _classAndIdImporter:CaseInsensitiveTLFFormatImporter;
		
		// Formats specified by formatting elements in the ancestry of the element being parsed currently 
		/** @private */
		static tlf_internal var _activeFormat:TextLayoutFormat = new TextLayoutFormat(); // to be applied to all flow elements
		/** @private */
		static tlf_internal var _activeParaFormat:TextLayoutFormat = new TextLayoutFormat(); // to be applied to paras only
		/** @private */
		static tlf_internal var _activeImpliedParaFormat:TextLayoutFormat = null;
		
		// The basis for relative font size calculation
		/** @private */
		tlf_internal var _baseFontSize:Number; 
		
		/** @private */
		tlf_internal static var _htmlImporterConfig:ImportExportConfiguration;
		
		private var _imageSourceResolveFunction:Function;
		private var _preserveBodyElement:Boolean = false;
		private var _importHtmlElement:Boolean = false;
		
		/** Constructor */
		public function TextFieldHtmlImporter()
		{
			createConfig();
			super(null, _htmlImporterConfig);
		}
		
		/** @private */
		tlf_internal static function createConfig():void
		{
			if (!_htmlImporterConfig)
			{
				_htmlImporterConfig = new ImportExportConfiguration();
				
				_htmlImporterConfig.addIEInfo("BR", BreakElement, BaseTextLayoutImporter.parseBreak, null); 
				_htmlImporterConfig.addIEInfo("P", ParagraphElement, TextFieldHtmlImporter.parsePara, null);
				_htmlImporterConfig.addIEInfo("SPAN", SpanElement, TextFieldHtmlImporter.parseSpan, null);
				_htmlImporterConfig.addIEInfo("A", LinkElement, TextFieldHtmlImporter.parseLink, null);
				_htmlImporterConfig.addIEInfo("IMG", InlineGraphicElement, TextFieldHtmlImporter.parseInlineGraphic, null);
				_htmlImporterConfig.addIEInfo("DIV", DivElement, TextFieldHtmlImporter.parseDiv, null);
				_htmlImporterConfig.addIEInfo("HTML", null, TextFieldHtmlImporter.parseHtmlElement, null);
				_htmlImporterConfig.addIEInfo("BODY", null, TextFieldHtmlImporter.parseBody, null);
			
				// formatting elements
				_htmlImporterConfig.addIEInfo("FONT", null, TextFieldHtmlImporter.parseFont, null);
				_htmlImporterConfig.addIEInfo("TEXTFORMAT", null, TextFieldHtmlImporter.parseTextFormat, null);
				_htmlImporterConfig.addIEInfo("U", null, TextFieldHtmlImporter.parseUnderline, null);
				_htmlImporterConfig.addIEInfo("I", null, TextFieldHtmlImporter.parseItalic, null);
				_htmlImporterConfig.addIEInfo("B", null, TextFieldHtmlImporter.parseBold, null);
				_htmlImporterConfig.addIEInfo("S", null, TextFieldHtmlImporter.parseStrikeThrough, null);
				
				// list stuff
				_htmlImporterConfig.addIEInfo("UL", null, BaseTextLayoutImporter.parseList, null);
				_htmlImporterConfig.addIEInfo("OL", null, BaseTextLayoutImporter.parseList, null);
				_htmlImporterConfig.addIEInfo("LI", null, TextFieldHtmlImporter.parseListItem, null);
				
			}
			
			// create these here - can't be done above
			if (_classAndIdDescription["CLASS"] === undefined)
			{
				_classAndIdDescription["CLASS"] = Property.NewStringProperty("CLASS", null, false, null);
				_paragraphFormatImporter = new HtmlCustomParaFormatImporter(TextLayoutFormat, _paragraphFormatDescription);
				_textFormatImporter = new TextFormatImporter(TextLayoutFormat, _textFormatDescription);
				_fontImporter = new FontImporter(TextLayoutFormat, _fontDescription);
				_fontMiscImporter = new CaseInsensitiveTLFFormatImporter(Dictionary, _fontMiscDescription);		
				_textFormatMiscImporter = new CaseInsensitiveTLFFormatImporter(Dictionary, _textFormatMiscDescription);
				_linkHrefImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_linkHrefDescription,false);
				_linkTargetImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_linkTargetDescription);
				_ilgFormatImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_imageDescription);
				_ilgMiscFormatImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_imageMiscDescription, false);
				_classAndIdImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_classAndIdDescription);
			}
		}
		
		/** @copy IHTMLExporter#imageSourceResolveFunction
		 * 
		 * @playerversion Flash 10.0
		 * @playerversion AIR 2.0
		 * @langversion 3.0
		 */
		public function get imageSourceResolveFunction():Function
		{ return _imageSourceResolveFunction; }
		public function set imageSourceResolveFunction(resolver:Function):void
		{ _imageSourceResolveFunction = resolver; }
		
		
		/** @copy IHTMLExporter#preserveBodyElement
		 * 
		 * @playerversion Flash 10.0
		 * @playerversion AIR 2.0
		 * @langversion 3.0
		 */		
		public function get preserveBodyElement():Boolean
		{ return _preserveBodyElement; }
		public function set preserveBodyElement(value:Boolean):void
		{ _preserveBodyElement = value; }
		
		/** @copy IHTMLExporter#preserveHTMLElement
		 *
		 * @playerversion Flash 10.0
		 * @playerversion AIR 2.0
		 * @langversion 3.0
		 */		
		public function get preserveHTMLElement():Boolean
		{ return _importHtmlElement; }
		public function set preserveHTMLElement(value:Boolean):void
		{ _importHtmlElement = value; }

		/** Parse and convert input data
		 * 
		 * @param source - the HTML string
		 */
		protected override function importFromString(source:String):TextFlow
		{	
			var textFlow:TextFlow;
			
			// Use toXML rather than the XML constructor because the latter expects
			// well-formed XML, which source may not be 
			var xml:XML = toXML(source);
			if (xml)
			{
				textFlow = importFromXML(xml);
				if (Configuration.playerEnablesArgoFeatures)
					System["disposeXML"](xml);
				
			}
			return textFlow;
		}

		/** Parse and convert input XML data
		 */
		protected override function importFromXML(xmlSource:XML):TextFlow
		{
			var textFlow:TextFlow = new TextFlow(_textFlowConfiguration);
			// always set html typeName - the convertfromstring to xml code wraps the content in an HTML element.  this makes it all match
			if (this.preserveHTMLElement)
				textFlow.typeName = "html";
			
			// Use font size specified in _textFlowConfiguration.textFlowInitialFormat as the base font size
			// If not specified, use 12
			_baseFontSize = textFlow.fontSize === undefined ? 12 : textFlow.fontSize;
			
			// Unlike other markup formats, the HTML format for TLF does not have a fixed root XML element.
			// <html> and <body> are optional, and flow elements may or may not be encapsulated in formatting 
			// elements like <i> or <textformat>. Use parseObject to handle any (expected) root element.
			parseObject(xmlSource.name().localName, xmlSource, textFlow);
			
			// If the last para is implied, there is nothing following it that'll trigger a reset. 
			// For most importers, this is fine (clear will eventually reset it), but the HTML importer has 
			// some special behavior associated with the reset (replacing BreakElements with para splits).
			// Explicitly do so now (must happen before normalization)
			resetImpliedPara();
			
			CONFIG::debug { textFlow.debugCheckNormalizeAll() ; }
			textFlow.normalize();
			textFlow.applyWhiteSpaceCollapse(null);
			
			return textFlow;
		}		

		/** @copy ConverterBase#clear()
		 * @private
		 */
		tlf_internal override function clear():void
		{
			// Reset active formats and base font size
			_activeParaFormat.clearStyles();
			_activeFormat.clearStyles();
			super.clear();
		}
		
		/** @private */
		tlf_internal override function createImpliedParagraph():ParagraphElement
		{
			var rslt:ParagraphElement;
			var savedActiveFormat:TextLayoutFormat = _activeFormat;
			if (_activeImpliedParaFormat)
				_activeFormat = _activeImpliedParaFormat;
			try
			{
				rslt = super.createImpliedParagraph();
			}
			finally
			{
				_activeFormat = savedActiveFormat;
			}
			return rslt;
		}

		/** @private */
		public override function createParagraphFromXML(xmlToParse:XML):ParagraphElement
		{
			var paraElem:ParagraphElement = new ParagraphElement();
				
			// Parse xml attributes for paragraph format
			var formatImporters:Array = [_paragraphFormatImporter, _classAndIdImporter];
			parseAttributes(xmlToParse, formatImporters);
			var paragraphFormat:TextLayoutFormat = new TextLayoutFormat(_paragraphFormatImporter.result as ITextLayoutFormat);
			
			// Apply paragraph format inherited from formatting elements
			if (_activeParaFormat)
				paragraphFormat.apply(_activeParaFormat);
			if (_activeFormat)
				paragraphFormat.apply(_activeFormat);
			
			// A <FONT/> that is the only child of a <P/> specifies formats that apply to the paragraph itself
			// Otherwise (i.e., if it has siblings), the formats apply to the elements nested within the <FONT/>
			// Check for the former case here
			var fontFormattingElement:XML = getSingleFontChild (xmlToParse);
			if (fontFormattingElement)
				paragraphFormat.apply(parseFontAttributes(fontFormattingElement));
				
			if (paragraphFormat.lineHeight !== undefined)
				paragraphFormat.leadingModel = LeadingModel.APPROXIMATE_TEXT_FIELD;
			
			paraElem.format = paragraphFormat;
			
			// Use the value of the 'class' attribute (if present) as styleName
			paraElem.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			paraElem.id =  _classAndIdImporter.getFormatValue("ID"); 
					
			return paraElem;
		}
		
		/** @private */
		static public function parseListItem(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			if (!(parent is ListElement))
			{
				var list:ListElement = importer.createListFromXML(null);
				importer.addChild(parent,list);
				CONFIG::debug { assert(list.parent == parent,"TextFieldHtmlImporter.parseListeItem: Bad call to addChild"); }
				parent = list;
			}
			
			var listItem:ListItemElement = importer.createListItemFromXML(xmlToParse);
			if (importer.addChild(parent, listItem))
			{
				importer.parseFlowGroupElementChildren(xmlToParse, listItem);
				//if parsing an empty list item, create a Paragraph for it.
				if (listItem.numChildren == 0)
					listItem.addChild(new ParagraphElement());	
			}
		}
		
		/** @private */
		public override function createListFromXML(xmlToParse:XML):ListElement	// No PMD
		{
			parseAttributes(xmlToParse, [ _classAndIdImporter ]);
			
			// try and make lists look something like TextField but with a bit more - do ordered lists as well not just bullets
			// textField indents lists on the left by 36 pixels.
			
			var list:ListElement = new ListElement();
			list.paddingLeft = 36;
			var name:String = xmlToParse ? xmlToParse.name().localName : null;
			list.listStyleType = name == "OL" ? ListStyleType.DECIMAL : ListStyleType.DISC;
			
			// TextField does equivalent of a 18 pixel start indent but that doesnt look nice with numbered lists.  
			// default bullet is around 4 pixels. so place the marker 14 pixels from the right side
			var lmf:ListMarkerFormat = new ListMarkerFormat();
			lmf.paragraphEndIndent = 14;
			list.listMarkerFormat = lmf;

			list.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			list.id =  _classAndIdImporter.getFormatValue("ID"); 		

			return list;
		}
		
		/** @private */
		public override function createListItemFromXML(xmlToParse:XML):ListItemElement	// No PMD
		{
			parseAttributes(xmlToParse, [ _classAndIdImporter ]);

			var listItem:ListItemElement = new ListItemElement();
			listItem.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			listItem.id =  _classAndIdImporter.getFormatValue("ID"); 		
			
			return listItem;
		}
		
		/** Parse the supplied XML into a paragraph. Parse the <p/> element and its children.
		 * @private
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parsePara(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var paraElem:ParagraphElement = importer.createParagraphFromXML(xmlToParse);
			
			if (importer.addChild(parent, paraElem))
			{
				// Parse children, but if there is only one child, a <FONT/>, skip to *its* children.
				// That's because the single <FONT/> chuld has already been parsed in createParagraphFromXML.
				var fontFormattingElement:XML = getSingleFontChild (xmlToParse);
				parseChildrenUnderNewActiveFormat (importer, fontFormattingElement ? fontFormattingElement : xmlToParse, paraElem, _activeFormat, null);
				
				//if parsing an empty paragraph, create a Span for it.
				if (paraElem.numChildren == 0)
					paraElem.addChild(importer.createImpliedSpan(""));
			}
			
			// Replace break elements with paragraph splits
			// This must happen before normalization else BreakElements may merge or become spans
			replaceBreakElementsWithParaSplits(paraElem);
		}
		
		/** Parse the supplied XML into a DivElement. Parse the <p/> element and its children.
		 * @private
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseDiv(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var elem:FlowGroupElement;
			if (parent.canOwnFlowElement(new DivElement()))
				elem = importer.createDivFromXML(xmlToParse);
			else
			{
				elem = importer.createSPGEFromXML(xmlToParse);
				elem.typeName = "div";
			}
			
			importer.addChild(parent,elem);
			importer.parseFlowGroupElementChildren(xmlToParse,elem);
		}
		
		static public function parseHtmlElement(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			// skip the element and descent to the children
			if (importer.preserveHTMLElement)
			{
				if (!(parent is TextFlow))
				{
					var newParent:FlowGroupElement = ((parent is ParagraphElement) || (parent is SubParagraphGroupElementBase)) ? new SubParagraphGroupElement() : new DivElement;
					parent.addChild(newParent);
					parent = newParent;
				}
				importer.parseAttributes(xmlToParse, [ _classAndIdImporter ]);
				parent.typeName = "html";
				parent.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
				parent.id =  _classAndIdImporter.getFormatValue("ID"); 		
			}
			importer.parseFlowGroupElementChildren(xmlToParse, parent, null, true);
		}
		
		static public function parseBody(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			// skip the element and descent to the children
			if (importer.preserveBodyElement)
			{
				var newParent:FlowGroupElement = ((parent is ParagraphElement) || (parent is SubParagraphGroupElementBase)) ? new SubParagraphGroupElement() : new DivElement;
				parent.addChild(newParent);
				parent = newParent;
				
				importer.parseAttributes(xmlToParse, [ _classAndIdImporter ]);
				parent.typeName = "body";
				parent.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
				parent.id =  _classAndIdImporter.getFormatValue("ID"); 		
			}
			importer.parseFlowGroupElementChildren(xmlToParse, parent, null, true);
		}

		
		public function createDivFromXML(xmlToParse:XML):DivElement
		{
			parseAttributes(xmlToParse, [ _classAndIdImporter ]);
			
			var divElement:DivElement = new DivElement();
			divElement.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			divElement.id =  _classAndIdImporter.getFormatValue("ID"); 		
			
			return divElement;
		}
		
		public function createSPGEFromXML(xmlToParse:XML):SubParagraphGroupElement
		{
			parseAttributes(xmlToParse, [ _classAndIdImporter ]);
			
			var spge:SubParagraphGroupElement = new SubParagraphGroupElement();
			spge.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			spge.id =  _classAndIdImporter.getFormatValue("ID"); 		
			
			return spge;
		}
		
		/** @private */
		protected override function onResetImpliedPara(para:ParagraphElement):void
		{
			// Replacing break elements with paragraph splits, even for implied paras
			replaceBreakElementsWithParaSplits (para);
		}
		
		/** If the provided xml has a single child <FONT.../>, get it
		 * @private
		 */
		static private function getSingleFontChild (xmlToParse:XML):XML
		{
			var children:XMLList = xmlToParse.children();
			if (children.length() == 1)
			{
				var child:XML = children[0];
				if (child.name().localName.toUpperCase() == "FONT")
					return child;
			}
			
			return null;
		}
			
		private function createLinkFromXML(xmlToParse:XML):LinkElement
		{
			var linkElem:LinkElement = new LinkElement();

			var formatImporters:Array = [ _linkHrefImporter, _linkTargetImporter, _classAndIdImporter ];
			parseAttributes(xmlToParse, formatImporters);
			
			linkElem.href = _linkHrefImporter.getFormatValue("HREF");
			linkElem.target = _linkTargetImporter.getFormatValue("TARGET");
			
			// Handle difference in defaults between TextField and TLF 
			// target "_self" vs. null (equivalent to "_blank")
			if (!linkElem.target)
				linkElem.target = "_self";
				
			//  Apply active format
			linkElem.format = _activeFormat;
			
			linkElem.styleName =  _classAndIdImporter.getFormatValue("CLASS"); 
			linkElem.id =  _classAndIdImporter.getFormatValue("ID"); 

			return linkElem;
		}
		
		/** Parse the supplied XML into a LinkElement. Parse the <a/> element and its children.
		 * @private
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseLink(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var linkElem:LinkElement = importer.createLinkFromXML(xmlToParse);
			
			if (importer.addChild(parent, linkElem))
			{
				parseChildrenUnderNewActiveFormat (importer, xmlToParse, linkElem, _activeFormat, null);
			}
		}	
		
		/** @private returns a string if its a simple span otherwise null */
		tlf_internal static function extractSimpleSpanText(xmlToParse:XML):String
		{
			var elemList:XMLList = xmlToParse[0].children();
			if (elemList.length() == 0)
				return "";
			if (elemList.length() != 1)
				return null;
			// sniff the first child and test if its a textelement
			for each (var child:XML in elemList)
				break;
			var elemName:String = child.name() ? child.name().localName : null;
			if (elemName != null)
				return null;
			
			var rslt:String = child.toString();
			return rslt ? rslt : "";
		}
		
		/** Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
		 * Insert the new content into its parent
		 * Note: Differs from BaseTextLayoutImporter.parseSpan in that it allows nested <span/> elements. 
		 * @private
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseSpan(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			// Use the value of the 'class' attribute (if present) as styleName
			importer.parseAttributes(xmlToParse,[_classAndIdImporter]);
			
			// if either class or id is set and its not a "simple" span then we need to create an SPGE and descend
			var classFormatValue:* = _classAndIdImporter.getFormatValue("CLASS");
			var idFormatValue:* = _classAndIdImporter.getFormatValue("ID");
			
			var simpleSpanText:String = extractSimpleSpanText(xmlToParse);
			
			if (simpleSpanText == null)
			{
				// if its an interesting span make an SPGE otherwise just parse the children
				if (classFormatValue !== undefined || idFormatValue !== undefined || !TextLayoutFormat.isEqual(_activeFormat,TextLayoutFormat.emptyTextLayoutFormat))
				{
					var spge:SubParagraphGroupElement = new SubParagraphGroupElement();
					spge.format = _activeFormat;
					spge.styleName = classFormatValue;
					spge.id = idFormatValue;
					spge.typeName = "span";
					importer.addChild(parent,spge);
					parent = spge;
				}
				parseChildrenUnderNewActiveFormat (importer, xmlToParse, parent, _activeFormat, null);
				return;
			}
			
			var span:SpanElement = new SpanElement();
			span.format = _activeFormat;
			span.styleName =  classFormatValue; 
			span.id =  idFormatValue; 
			span.text = simpleSpanText;

			importer.addChild(parent, span);
		} 
		
		/** create an implied span with specified text */
		public override function createImpliedSpan(text:String):SpanElement
		{
			var span:SpanElement = super.createImpliedSpan(text);
			span.format = _activeFormat;
			return span;
		}
	
		/** @private */
		protected function createInlineGraphicFromXML(xmlToParse:XML):InlineGraphicElement
		{				
			var imgElem:InlineGraphicElement = new InlineGraphicElement();

			var formatImporters:Array = [_ilgFormatImporter, _ilgMiscFormatImporter, _classAndIdImporter];	
			parseAttributes(xmlToParse,formatImporters);
			
			var source:String = _ilgMiscFormatImporter.getFormatValue("SRC");
			imgElem.source = _imageSourceResolveFunction != null ? _imageSourceResolveFunction(source) : source;
				
			// if not defined then let InlineGraphic set its own default
			imgElem.height = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.height,_ilgFormatImporter.getFormatValue("HEIGHT"));
			imgElem.width  = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.width,_ilgFormatImporter.getFormatValue("WIDTH"));
				
			var floatVal:String = _ilgMiscFormatImporter.getFormatValue("ALIGN");
			// Handle difference in defaults between TextField and TLF 
			// float "left" vs. "none"
			if (floatVal == Float.LEFT || floatVal == Float.RIGHT)
				imgElem.float = floatVal;
			
			//  Apply active format
			imgElem.format = _activeFormat;
			imgElem.id = _classAndIdImporter.getFormatValue("ID");
			imgElem.styleName = _classAndIdImporter.getFormatValue("CLASS");
			
			return imgElem;
		}

		/** Parse the supplied XML into an InlineGraphicElement. Parse the <img/> element.
		 * @private
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the new content
		 */
		static public function parseInlineGraphic(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var ilg:InlineGraphicElement = importer.createInlineGraphicFromXML(xmlToParse);
			importer.addChild(parent, ilg);
		}
		
		/** @private */
		public override function createTabFromXML(xmlToParse:XML):TabElement
		{
			return null; // no tabs in HTML
		}
			
		/** Parse the attributes of the <Font/> formatting element and returns the corresponding TLF format
		 * @private
		 */
		protected function parseFontAttributes(xmlToParse:XML):ITextLayoutFormat
		{
			var formatImporters:Array = [_fontImporter, _fontMiscImporter];
			parseAttributes(xmlToParse, formatImporters);
			
			var newFormat:TextLayoutFormat = new TextLayoutFormat(_fontImporter.result as ITextLayoutFormat);
			
			var kerning:String = _fontMiscImporter.getFormatValue("KERNING");
			if (kerning)
			{
				var kerningVal:Number = Number(kerning);
				newFormat.kerning = kerningVal == 0 ? Kerning.OFF : Kerning.AUTO;
			}
			
			var size:String = _fontMiscImporter.getFormatValue("SIZE");
			if (size)
			{
				var sizeVal:Number = TextLayoutFormat.fontSizeProperty.setHelper(NaN, size);
				if (!isNaN(sizeVal))
				{
					if (size.search(/\s*(-|\+)/) != -1) // leading whitespace followed by + or -
						sizeVal += _baseFontSize;		// implies relative font sizes
					newFormat.fontSize = sizeVal;
				}
			}
			
			return newFormat;
		}
		
		/** Parse the <Font/> formatting element
		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseFont(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var newFormat:ITextLayoutFormat = importer.parseFontAttributes (xmlToParse);
			parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importer, xmlToParse, parent, newFormat);
		}
		
		/** Parse the <TextFormat> formatting element
		 * Calculates the new format to apply to _activeParaFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseTextFormat(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{	
			var formatImporters:Array = [_textFormatImporter, _textFormatMiscImporter];
			importer.parseAttributes(xmlToParse, formatImporters);
			
			var newFormat:TextLayoutFormat = new TextLayoutFormat(_textFormatImporter.result as ITextLayoutFormat);
			
			var blockIndent:* = _textFormatMiscImporter.getFormatValue("BLOCKINDENT");
			if (blockIndent !== undefined)
			{
				// TODO: Nested <TextFormat/>?
				blockIndent = TextLayoutFormat.paragraphStartIndentProperty.setHelper(undefined, blockIndent);
				if (blockIndent !== undefined)
				{
					var blockIndentVal:Number = Number(blockIndent);
					newFormat.paragraphStartIndent = newFormat.paragraphStartIndent === undefined ? blockIndentVal : newFormat.paragraphStartIndent + blockIndentVal;
				}
			}
			
			// lineHeight is the only textformat property that must be copied down into subparagraph elements
			var saveLineHeight:* = _activeFormat.lineHeight;
			if (parent is ParagraphElement)
			{
				if (parent.numChildren == 0)
				{
					// if <textFormat> is the first child then promote all the settings to the Paragraph
					var format:TextLayoutFormat = new TextLayoutFormat(parent.format);
					format.apply(newFormat);
					// same as createParagraphFromXML
					if (format.lineHeight !== undefined)
						format.leadingModel = LeadingModel.APPROXIMATE_TEXT_FIELD;
					parent.format = format;
					newFormat.clearStyles();
				}
				else if (newFormat.lineHeight !== undefined)
					_activeFormat.lineHeight = newFormat.lineHeight;
			}

			parseChildrenUnderNewActiveFormat (importer, xmlToParse, parent, _activeParaFormat, newFormat, true);
			
			_activeFormat.lineHeight = saveLineHeight;
		}
		
		/** Parse the <b> formatting element
		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseBold(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{	
			var newFormat:TextLayoutFormat = new TextLayoutFormat();
			newFormat.fontWeight = flash.text.engine.FontWeight.BOLD;
			
			parseChildrenUnderNewActiveFormatWithImpliedParaFormat (importer, xmlToParse, parent, newFormat);
		}
		
		/** Parse the <i> formatting element
		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseItalic(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{	
			var newFormat:TextLayoutFormat = new TextLayoutFormat();
			newFormat.fontStyle = flash.text.engine.FontPosture.ITALIC;
			parseChildrenUnderNewActiveFormatWithImpliedParaFormat (importer, xmlToParse, parent, newFormat);
		}
		
		/** Parse the <b> formatting element
		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseStrikeThrough(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{	
			var newFormat:TextLayoutFormat = new TextLayoutFormat();
			newFormat.lineThrough = true;
			parseChildrenUnderNewActiveFormatWithImpliedParaFormat (importer, xmlToParse, parent, newFormat);
		}
		
		/** Parse the <u> formatting element
		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
		 * @private
		 */
		static public function parseUnderline(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement):void
		{	
			var newFormat:TextLayoutFormat = new TextLayoutFormat();
			newFormat.textDecoration = flashx.textLayout.formats.TextDecoration.UNDERLINE;
			parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importer, xmlToParse, parent, newFormat);

		}
		
		/** @private */
		static protected function parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement, newFormat:ITextLayoutFormat):void
		{
			var oldActiveImpliedParaFormat:TextLayoutFormat = _activeImpliedParaFormat;
			if (_activeImpliedParaFormat == null)
				_activeImpliedParaFormat = new TextLayoutFormat(_activeFormat);
			try
			{
				parseChildrenUnderNewActiveFormat(importer, xmlToParse, parent, _activeFormat, newFormat, true);
			}
			finally
			{
				_activeImpliedParaFormat = oldActiveImpliedParaFormat;
			}
		}
		
		/** Updates the current active format and base font size as specified, parses children, and restores the active format and base font size
		 * There are two different use cases for this method:
		 * - Parsing children of a formatting XML element like <Font/> or <TextFormat/>. In this case, the TLF format corresponding to the formatting element
		 * (newFormat) is applied to the currently active format (_activeFormat in the case of <Font/> and _activeParaFormat in the case of <TextFormat/>). 
		 * Children of the formatting element are parsed under this new active format.
		 * - Parsing children of a flow XML element like <P/> or <A/>. In this case, newFormat is null and the currently active format (_activeFormat) is reset.
		 * Children of the flow element are parsed under this newly reset format. This is to avoid redundancy (the format is already applied to the flow element). 
		 * 
		 * @param importer	parser object
		 * @param xmlToParse	content to parse
		 * @param parent 		the parent for the parsed children
		 * @param currFormat	the active format (_activeFormat or _activeParaFormat)
		 * @param newFormat		the format to apply to currFormat while the children are being parsed. If null, currFormat is to be reset.
		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element). See BaseTextLayoutImporter.parseFlowGroupElementChildren
		 * @private
		 */
		static protected function parseChildrenUnderNewActiveFormat (importer:TextFieldHtmlImporter, xmlToParse:XML, parent:FlowGroupElement, currFormat:TextLayoutFormat, newFormat:ITextLayoutFormat, chainedParent:Boolean=false):void
		{
			// Remember the current state
			var restoreBaseFontSize:Number = importer._baseFontSize;
			var restoreStyles:Object = Property.shallowCopy(currFormat.getStyles());
			
			if (newFormat)
			{
				// Update base font size based on the new format
				if (newFormat.fontSize !== undefined)
					importer._baseFontSize = newFormat.fontSize; 
					
				// Apply the new format
				currFormat.apply(newFormat);
			}
			else
			{
				// Base font size remains unchanged
				
				// Reset the new format
				currFormat.clearStyles();
			}
			
			try
			{
				var beforeCount:int = parent.numChildren;
				importer.parseFlowGroupElementChildren(xmlToParse, parent, null, chainedParent);
				// if nothing was added create something - otherwise this construct fails <p><b/></p>
				if (beforeCount == parent.numChildren)
				{
					var span:SpanElement = importer.createImpliedSpan("");
					importer.addChild(parent,span);
				}
			}
			finally
			{
				// Restore 
				currFormat.setStyles(restoreStyles,false);
				importer._baseFontSize = restoreBaseFontSize;
			}
		}
		
		/** @private */
		protected override function handleUnknownAttribute(elementName:String, propertyName:String):void
		{
			// A toss-up: report error or ignore? Ignore for now
			// If we do end up reporting error, we should add exceptions for documented attributes that we don't handle
			// like align on <img/>
		}
		
		/** @private */
		protected override function handleUnknownElement(name:String, xmlToParse:XML, parent:FlowGroupElement):void
		{
			var newParent:FlowGroupElement;	// scratch
			// Not an error (it may be a styling element like <h1/>); continue parsing children
			
			// a couple of cases
			// 1) must make a div/spge - if activeFormat or id or stylename is set OR parent is a ListElement (otherwise we wind up trying to put ListItems in a Div which is not supported)
			// 2) may make a div/spge - if more than one child is added to parent OR the added child has an id/stylename/typename
			// 3) otherwise just set the typeName of the single added child
			
			// Use the value of the 'class' attribute (if present) as styleName
			parseAttributes(xmlToParse,[_classAndIdImporter]);
			
			// if either class or id is set and its not a "simple" span then we need to create an SPGE and descend
			var classFormatValue:* = _classAndIdImporter.getFormatValue("CLASS");
			var idFormatValue:* = _classAndIdImporter.getFormatValue("ID");
			
			if (classFormatValue !== undefined || idFormatValue !== undefined || !TextLayoutFormat.isEqual(_activeFormat,TextLayoutFormat.emptyTextLayoutFormat) || (parent is ListElement))
			{
				newParent = ((parent is ParagraphElement) || (parent is SubParagraphGroupElementBase)) ? new SubParagraphGroupElement() : new DivElement;
				addChild(parent, newParent);
					
				newParent.format = _activeFormat;
				newParent.typeName = name.toLowerCase();
				newParent.styleName = classFormatValue;
				newParent.id = idFormatValue;
				parseChildrenUnderNewActiveFormat (this, xmlToParse, newParent, _activeFormat, null);	
				return;
			}
			
			var befNumChildren:int = parent.numChildren;
			parseFlowGroupElementChildren(xmlToParse, parent, null, true);
			
			// nothing got added - the custom element will be normalized away so just ignore it
			if (befNumChildren == parent.numChildren)
				return;

			if (befNumChildren+1 == parent.numChildren)
			{
				// exactly one child was added - just tag it with the typeName if possible
				var addedChild:FlowElement = parent.getChildAt(befNumChildren);
				if (addedChild.id == null && addedChild.styleName == null && addedChild.typeName == addedChild.defaultTypeName)
				{
					addedChild.typeName = name.toLowerCase();
					return;
				}
			}
			
			// have to make one - case 1)
			newParent = ((parent is ParagraphElement) || (parent is SubParagraphGroupElementBase)) ? new SubParagraphGroupElement() : new DivElement;
			newParent.typeName = name.toLowerCase();
			newParent.replaceChildren(0,0,parent.mxmlChildren.slice(befNumChildren));
			addChild(parent,newParent);
		}										
		
		tlf_internal override function  parseObject(name:String, xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object=null):void
		{
			// override to allow upper case tag names
			super.parseObject(name.toUpperCase(), xmlToParse, parent, exceptionElements);
		}
		
		/** @private */
		protected override function checkNamespace(xmlToParse:XML):Boolean
		{	
			/* Ignore namespace */
			return true;
		}
		
		/** Splits the paragraph wherever a break element occurs and removes the latter
		 * This is to replicate TextField handling of <br/>: splits the containing paragraph (implied or otherwise)
		 * The <br/> itself doesn't survive.
		 * @private
		 */
		static protected function replaceBreakElementsWithParaSplits(para:ParagraphElement):void
		{
			// performance: when splitting the paragraph into multiple paragraphs take it out of the TextFlow
			var paraArray:Array;
			var paraIndex:int;
			var paraParent:FlowGroupElement;
	
			// Find each BreakElement and split into a new paragraph
			var elem:FlowLeafElement = para.getFirstLeaf();
			while (elem)
			{
				if (!(elem is BreakElement))
				{
					elem = elem.getNextLeaf(para);
					continue;					
				}
				if (!paraArray)
				{
					paraArray = [ para ];
					paraParent = para.parent;
					paraIndex = paraParent.getChildIndex(para);
					paraParent.removeChildAt(paraIndex);
				}
					
				// Split the para right after the BreakElement
				//CONFIG::debug { assert(elem.textLength == 1,"Bad TextLength in BreakElement"); }
				CONFIG::debug {assert( para.getAbsoluteStart() == 0,"Bad paragraph in replaceBreakElementsWithParaSplits"); }
				para = para.splitAtPosition(elem.getAbsoluteStart()+elem.textLength) as ParagraphElement;
				paraArray.push(para);
					
				// Remove the BreakElement
				elem.parent.removeChild(elem);	
				
				// point elem to the first leaf of the new paragraph
				elem = para.getFirstLeaf();
			}
			
			if (paraArray)
				paraParent.replaceChildren(paraIndex,paraIndex,paraArray);
		}
		
		/** HTML parsing code
		 *  Uses regular expressions for recognizing constructs like comments, tags etc.
		 *  and a hand-coded parser to recognize the document structure and covert to well-formed xml
		 *  TODO-1/16/2009:List caveats
		 */ 
		
		/* Regex for stuff to be stripped: a comment, processing instruction, or a declaration
		 *
		 * <!--.*?--> - comment
		 *   <!-- - start comment
		 *   .*? - anything (including newline character, thanks to the s flag); the ? prevents a greedy match (which could match a --> later in the string) 
		 *  --> - end comment
		 *  
		 * <\?(".*?"|'.*?'|[^>]+)*> - processing instruction
		 *   <\? - start processing instruction
		 *   (".*?"|'.*?'|[^>]+)* - 0 or more of the following (interleaved in any order)
		 *     ".*?" - anything (including >) so long as it is within double quotes; the ? prevents a greedy match (which could match everything until a later " in the string) 
		 *     '.*?' - anything (including >) so long as it is within single quotes; the ? prevents a greedy match (which could match everything until a later ' in the string)
		 *     [^>"']+ - one or more characters other than > (because > ends the processing instruction), " (handled above), ' (handled above) 
		 *   > - end processing instruction
		 *
		 * <!(".*?"|'.*?'|[^>"']+)*> - declaration; 
		 * TODO-1/15/2009:not sure if a declaration can contain > within quotes. Assuming it can, the regex is  
		 *  is exactly like processing instruction above except it uses a ! instead of a ?
		 * @private
		 */
		/** @private */
		tlf_internal static const stripRegex:RegExp = /<!--.*?-->|<\?(".*?"|'.*?'|[^>"']+)*>|<!(".*?"|'.*?'|[^>"']+)*>/sg;
						
		/* Regular expression for an HTML tag
		 * < - open
		 *
		 * (\/?) - start modifier; 0 or 1 occurance of one of /
		 *
		 * (\w+) - tag name; 1 or more name characters
		 *
		 * ((?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?)*) - attributes; 0 or more of the following
		 *   (?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?) - attribute; 1 or more space, followed by 1 or more name characters optionally followed by
		 *      \s*=\s*(?:".*?"|'.*?'|[\w\.]+) - attribute value assignment; optional space followed by = followed by more optional space followed by one of
		 *         ".*?" - quoted attribute value (using double quotes); the ? prevents a greedy match (which could match everything until a later " in the string)
		 *         '.*?' - quoted attribute value (using single quotes); the ? prevents a greedy match ((which could match everything until a later ' in the string)
		 *         [\w\.]+ - unquoted attribute value; can only contain name characters or a period
		 *  Note: ?: specifies a non-capturing group (i.e., match won't be recorded or used as a numbered back-reference)
		 *
		 * \s* - optional space
		 *
		 * (\/?) - end modifer (0 or 1 occurance of /)
		 *
		 * > - close
		 * @private
		 */
		/** @private */
		tlf_internal static const tagRegex:RegExp = /<(\/?)(\w+)((?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?)*)\s*(\/?)>/sg;
		
		/** Regular expression for an attribute. Except for grouping differences, this regex is the same as the one that appears in tagRegex
		 * @private
		 */
		tlf_internal static const attrRegex:RegExp = /\s+(\w+)(?:\s*=\s*(".*?"|'.*?'|[\w\.]+))?/sg;
		
		/** Wrapper for core HTML parsing code that manages XML settings during the process
		 * @private
		 */
		protected function toXML(source:String):XML
		{
			var xml:XML;
			
			var originalSettings:Object = XML.settings();
			try
			{
				XML.ignoreProcessingInstructions = false;		
				XML.ignoreWhitespace = false;	

				xml = toXMLInternal(source);				
			}			
			finally
			{
				XML.setSettings(originalSettings);
			}	
			
			return xml;
		}	
		
		/** Convert HTML string to well-formed xml, accounting for the following HTML oddities
		 * 
		 * 1) Start tags are optional for some elements.
		 * Optional start tag not specified&lt;/html&gt;
		 * TextField dialect: This is true for all elements. 
		 * 
		 * 2) End tags are optional for some elements. Elements with missing end tags may be implicitly closed by
		 *    a) start-tag for a peer element
		 *    &lt;p&gt;p element without end tag; closed by next p start tag
		 *    &lt;p&gt;closes previous p element with missing end tag&lt;/p&gt;
		 * 
		 *    b) end-tag for an ancestor element 
		 * 	  &lt;html&gt;&lt;p&gt;p element without end tag; closed by next end tag of an ancestor&lt;/html&gt;
		 *     TextField dialect: This is true for all elements. 
		 * 
		 * 3) End tags are forbidden for some elements
		 * &lt;br&gt; and &lt;br/&gt; are valid, but &lt;br&gt;&lt;/br&gt; is not
		 * TextField dialect: Does not apply. 
		 * 
		 * 4) Element and attribute names may use any case
		 * &lt;P ALign="left"&gt;&lt;/p&gt;
		 * 
		 * 5) Attribute values may be unquoted
		 * &lt;p align=left/&gt;
		 * 
		 * 6) Boolean attributed may assume a minimized form
		 * &lt;p selected/&gt; is equivalent to &lt;p selected="selected"/&gt;
		 * @private
		 */	
		protected function toXMLInternal(source:String):XML
		{
			// Strip out comments, processing instructions and declaratins	
			source = source.replace(stripRegex, "");
			
			// Parse the source, looking for tags and interleaved text content, creating an XML hierarchy in the process.
			// At any given time, there is a chain of 'open' elements corresponding to unclosed tags, the innermost of which is 
			// tracked by the currElem. Content (element or text) parsed next is added as a child of currElem.
			
			// Root of the XML hierarchy (set to <html/> because the html start tag is optional)
			// Note that source may contain an html start tag, in which case we'll end up with two such elements
			// This is not quite correct, but handled by the importer  
			var root:XML = <HTML/>; 
			var currElem:XML = root;  
			
			var lastIndex:int = tagRegex.lastIndex = 0;
			var openElemName:String;
						
			do
			{						
				var result:Object = tagRegex.exec(source);
				if (!result)
				{
					// No more tags: add text (starting at search index) as a child of the innermost open element and break out
					appendTextChild (currElem, source.substring(lastIndex));
					break;
				}
				
				if (result.index != lastIndex)
				{
					// Add text between tags as a child of the innermost open element
					appendTextChild (currElem, source.substring(lastIndex, result.index));
				}
				
				var tag:String = result[0]; // entire tag
				var hasStartModifier:Boolean = (result[1] == "\/"); // modifier after < (/ for end tag)
				var name:String = result[2].toUpperCase();  // name; use lower case
				var attrs:String = result[3];  // attributes; including whitespace
				var hasEndModifier:Boolean = (result[4] == "\/"); // modifier before > (/ for composite start and end tag)

				if (!hasStartModifier) // start tag 
				{	
					// Special case for implicit closing of <p>
					// TODO-12/23/2008: this will need to be handled more generically				
					if (name == "P" && currElem.name().localName == "P")
						currElem = currElem.parent();
						
					// Create an XML element by constructing a tag that can be fed to the XML constructor. Specifically, ensure
					// - it is a composite tag (start and end tag together) using the terminating slash shorthand
					// - element and attribute names are lower case (this is not required, but doesn't hurt)
					// - attribute values are quoted  	
					// - boolean attributes are fully specified (e.g., selected="selected" rather than selected)
					tag = "<" + name;
					do
					{
						var innerResult:Object = attrRegex.exec(attrs);
						if (!innerResult)
							break;
							
						var attrName:String = innerResult[1].toUpperCase();
						tag += " " + attrName + "="; 
						var val:String = innerResult[2] ? innerResult[2] : attrName; /* boolean attribute with implied value equal to attribute name */
						var startChar:String = val.charAt(0); 
						tag += ((startChar == "'" || startChar == "\"") ? val : ("\"" + val + "\""));
						
					} while (true);	 
					tag += "\/>";
					
					// Add the corresponding element as a child of the innermost open element 
					currElem.appendChild(new XML(tag));
					
					// The new element becomes the innermost open element unless it is already closed because
					// - this is a composite start and end tag (i.e., has an end modifier) 
					// - the start tag itself implies closure
					if (!hasEndModifier && !doesStartTagCloseElement(name))
						currElem = currElem.children()[currElem.children().length()-1];	
				}	
				else // end tag
				{	
					if (hasEndModifier || attrs.length)
					{
						reportError(GlobalSettings.resourceStringFunction("malformedTag",[tag]));
					}
					else
					{
						/*
						// Does not apply to TextField dialect
						if (isEndTagForbidden(name))
						{
							xxxreportError("End tag is not allowed for element " + name); NOTE : MAKE A LOCALIZABLE ERROR IF THIS COMES BACK
							return null;
						}*/
					
						// Move up the chain of open elements looking for a matching name
						// The matching element is closed and its parent becomes the innermost open element
						// Report error if matching element is not found and it requires a start tag
						// All intermediate open elements are also closed provided they don't require end tags
						// Report error if an intermediate element requires end tags
						var openElem:XML = currElem;
						do
						{
							openElemName = openElem.name().localName; 
							openElem = openElem.parent();
							
							if (openElemName == name)
							{
								currElem = openElem;
								break;
							}
							/*
							// Does not apply to TextField dialect
							else if (isEndTagRequired(openElemName))
							{
								xxxreportError("Missing end tag for element " + openElemName);
								return null;
							}*/
	
							
							if (!openElem)
							{
								// Does not apply to TextField dialect
								/*if (isStartTagRequired(name))
								{
									xxxreportError("Unexpected end tag " + name);
									return null;
								}*/
								break;
							}					
						}
						while (true);
					}
				}
				
				lastIndex = tagRegex.lastIndex;
				if (lastIndex == source.length)
					break; // string completely parsed
					
			} while (currElem); // null currElem means <html/> has been closed, so ignore everything else		
			
			// No more string to parse, specifically, no more end tags. 
			// Validate that remaining open elements do not require end tags.
			// Does not apply to TextField dialect
			/* while (currElem)
			{
				openElemName = currElem.name().localName; 
				if (isEndTagRequired(openElemName))
				{
					xxxreportError("Missing end tag for element " + openElemName);
					return null;
				}
				currElem = currElem.parent();
			}*/	
			
			return root;
		}
		
		/** @private */
		protected function doesStartTagCloseElement (tagName:String):Boolean
		{
			switch (tagName)
			{
				case "BR":
				case "IMG":
					return true;
				default:
					return false;
			}
		}
		
		/** @private */
		tlf_internal static const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g;	

		/** Adds text as a descendant of the specified XML element. Adds an intermediate <span> element is created if parent is not a <span>
		 *  No action is taken for whitespace-only text
		 * @private
		 */
		protected function appendTextChild(parent:XML, text:String):void
		{
			// No whitespace collapse
			// if (text.match(anyPrintChar).length != 0) 
			{
				var parentIsSpan:Boolean = (parent.localName() == "SPAN");
				var elemName:String = parentIsSpan ? "DUMMY" : "SPAN";
				
				//var xml:XML = <{elemName}/>;
				//xml.appendChild(text);
				// The commented-out code above doesn't handle character entities like &lt; 
				// The following lets the XML constructor handle them 
				var xmlText:String = "<" + elemName + ">" + text + "<\/" + elemName + ">";
				try
				{
					var xml:XML = new XML(xmlText);
					parent.appendChild(parentIsSpan ? xml.children()[0] : xml);
				}
				catch (e:*)
				{
					// Report malformed content like "<" instead of "&lt;"
					reportError(GlobalSettings.resourceStringFunction("malformedMarkup",[text]));
				}
					
			}
		}	
	}
}

import flashx.textLayout.conversion.TLFormatImporter;

/** Specialized to provide case insensitivity (as required by TEXT_FIELD_HTML_FORMAT)
 *  Keys need to be lower-cased. Values may or may not based on a flag passed to the constructor. 
 */
class CaseInsensitiveTLFFormatImporter extends TLFormatImporter
{
	private var _convertValuesToLowerCase:Boolean;

	public function CaseInsensitiveTLFFormatImporter(classType:Class,description:Object, convertValuesToLowerCase:Boolean=true)
	{
		_convertValuesToLowerCase = convertValuesToLowerCase;
		
		var lowerCaseDescription:Object = new Object();
		for (var prop:Object in description)
		{
			lowerCaseDescription[prop.toUpperCase()] = description[prop];
		}
		
		super(classType, lowerCaseDescription);
	}
	
	public override function importOneFormat(key:String,val:String):Boolean
	{
		return super.importOneFormat(key.toUpperCase(), _convertValuesToLowerCase ? val.toLowerCase() : val);  
	} 
	
	public function getFormatValue (key:String):*
	{
		return result ? result[key.toUpperCase()] : undefined;
	}
	
}

class HtmlCustomParaFormatImporter extends TLFormatImporter
{
	public function HtmlCustomParaFormatImporter(classType:Class,description:Object)
	{
		super(classType,description);
	}
	
	public override function importOneFormat(key:String,val:String):Boolean
	{
		key = key.toUpperCase();
		
		if (key == "ALIGN")
			key = "textAlign";
		return super.importOneFormat(key,val.toLowerCase()); // covert val to lowercase because TLF won't accept, say, "RIGHT"
	} 
}

class TextFormatImporter extends TLFormatImporter
{
	public function TextFormatImporter(classType:Class,description:Object)
	{
		super(classType,description);
	}
	
	public override function importOneFormat(key:String,val:String):Boolean
	{
		key = key.toUpperCase();
		
		if (key == "LEFTMARGIN")
			key = "paragraphStartIndent"; // assumed to be left-to-right text since we don't handle DIR attribute
		else if (key == "RIGHTMARGIN")
			key = "paragraphEndIndent";   // assumed to be left-to-right text since we don't handle DIR attribute
		else if (key == "INDENT")
			key = "textIndent";
		else if (key == "LEADING")
			key = "lineHeight";
		else if (key == "TABSTOPS")
		{
			key = "tabStops";
			// Comma-delimited in TextField HTML format, space delimited in TLF
			val = val.replace(/,/g, ' '); 
		}
		return super.importOneFormat(key,val); // no case-coversion required, values for these formats in TLF are case-insensitive
	} 
}

class FontImporter extends TLFormatImporter
{
	public function FontImporter(classType:Class,description:Object)
	{
		super(classType,description);
	}
	
	public override function importOneFormat(key:String,val:String):Boolean
	{
		key = key.toUpperCase();
		if (key == "LETTERSPACING")
			key = "trackingRight";
		else if (key == "FACE")
			key = "fontFamily";
		else if (key == "COLOR")
			key = "color";
		return super.importOneFormat(key,val);  // no case-coversion required, values for these formats in TLF are case-insensitive
	} 
}

