/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.forms.widgets;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.swt.SWT;
import org.eclipse.ui.forms.HyperlinkSettings;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class FormTextModel {
	private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
			.newInstance();

	private boolean whitespaceNormalized = true;

	private Vector paragraphs;

	private IFocusSelectable[] selectableSegments;

	private int selectedSegmentIndex = -1;
	
	private int savedSelectedLinkIndex = -1;

	private HyperlinkSettings hyperlinkSettings;

	public static final String BOLD_FONT_ID = "f.____bold"; //$NON-NLS-1$

	//private static final int TEXT_ONLY_LINK = 1;

	//private static final int IMG_ONLY_LINK = 2;

	//private static final int TEXT_AND_IMAGES_LINK = 3;

	public FormTextModel() {
		reset();
	}

	/*
	 * @see ITextModel#getParagraphs()
	 */
	public Paragraph[] getParagraphs() {
		if (paragraphs == null)
			return new Paragraph[0];
		return (Paragraph[]) paragraphs
				.toArray(new Paragraph[paragraphs.size()]);
	}

	public String getAccessibleText() {
		if (paragraphs == null)
			return ""; //$NON-NLS-1$
		StringBuffer sbuf = new StringBuffer();
		for (int i = 0; i < paragraphs.size(); i++) {
			Paragraph paragraph = (Paragraph) paragraphs.get(i);
			String text = paragraph.getAccessibleText();
			sbuf.append(text);
		}
		return sbuf.toString();
	}

	/*
	 * @see ITextModel#parse(String)
	 */
	public void parseTaggedText(String taggedText, boolean expandURLs) {
		if (taggedText == null) {
			reset();
			return;
		}
		try {
			InputStream stream = new ByteArrayInputStream(taggedText
					.getBytes("UTF8")); //$NON-NLS-1$
			parseInputStream(stream, expandURLs);
		} catch (UnsupportedEncodingException e) {
			SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT, e);
		}
	}

	public void parseInputStream(InputStream is, boolean expandURLs) {

		documentBuilderFactory.setNamespaceAware(true);
		documentBuilderFactory.setIgnoringComments(true);

		reset();
		try {
			DocumentBuilder parser = documentBuilderFactory
					.newDocumentBuilder();
			InputSource source = new InputSource(is);
			Document doc = parser.parse(source);
			processDocument(doc, expandURLs);
		} catch (ParserConfigurationException e) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT, e);
		} catch (SAXException e) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT, e);
		} catch (IOException e) {
			SWT.error(SWT.ERROR_IO, e);
		}
	}

	private void processDocument(Document doc, boolean expandURLs) {
		Node root = doc.getDocumentElement();
		NodeList children = root.getChildNodes();
		processSubnodes(paragraphs, children, expandURLs);
	}

	private void processSubnodes(Vector plist, NodeList children, boolean expandURLs) {
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.TEXT_NODE) {
				// Make an implicit paragraph
				String text = getSingleNodeText(child);
				if (text != null && !isIgnorableWhiteSpace(text, true)) {
					Paragraph p = new Paragraph(true);
					p.parseRegularText(text, expandURLs, true,
							getHyperlinkSettings(), null);
					plist.add(p);
				}
			} else if (child.getNodeType() == Node.ELEMENT_NODE) {
				String tag = child.getNodeName().toLowerCase();
				if (tag.equals("p")) { //$NON-NLS-1$
					Paragraph p = processParagraph(child, expandURLs);
					if (p != null)
						plist.add(p);
				} else if (tag.equals("li")) { //$NON-NLS-1$
					Paragraph p = processListItem(child, expandURLs);
					if (p != null)
						plist.add(p);
				}
			}
		}
	}

	private Paragraph processParagraph(Node paragraph, boolean expandURLs) {
		NodeList children = paragraph.getChildNodes();
		NamedNodeMap atts = paragraph.getAttributes();
		Node addSpaceAtt = atts.getNamedItem("addVerticalSpace"); //$NON-NLS-1$
		boolean addSpace = true;

		if (addSpaceAtt == null)
			addSpaceAtt = atts.getNamedItem("vspace"); //$NON-NLS-1$

		if (addSpaceAtt != null) {
			String value = addSpaceAtt.getNodeValue();
			addSpace = value.equalsIgnoreCase("true"); //$NON-NLS-1$
		}
		Paragraph p = new Paragraph(addSpace);

		processSegments(p, children, expandURLs);
		return p;
	}

	private Paragraph processListItem(Node listItem, boolean expandURLs) {
		NodeList children = listItem.getChildNodes();
		NamedNodeMap atts = listItem.getAttributes();
		Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");//$NON-NLS-1$
		Node styleAtt = atts.getNamedItem("style");//$NON-NLS-1$
		Node valueAtt = atts.getNamedItem("value");//$NON-NLS-1$
		Node indentAtt = atts.getNamedItem("indent");//$NON-NLS-1$
		Node bindentAtt = atts.getNamedItem("bindent");//$NON-NLS-1$
		int style = BulletParagraph.CIRCLE;
		int indent = -1;
		int bindent = -1;
		String text = null;
		boolean addSpace = true;

		if (addSpaceAtt != null) {
			String value = addSpaceAtt.getNodeValue();
			addSpace = value.equalsIgnoreCase("true"); //$NON-NLS-1$
		}
		if (styleAtt != null) {
			String value = styleAtt.getNodeValue();
			if (value.equalsIgnoreCase("text")) { //$NON-NLS-1$
				style = BulletParagraph.TEXT;
			} else if (value.equalsIgnoreCase("image")) { //$NON-NLS-1$
				style = BulletParagraph.IMAGE;
			} else if (value.equalsIgnoreCase("bullet")) { //$NON-NLS-1$
				style = BulletParagraph.CIRCLE;
			}
		}
		if (valueAtt != null) {
			text = valueAtt.getNodeValue();
			if (style == BulletParagraph.IMAGE)
				text = "i." + text; //$NON-NLS-1$
		}
		if (indentAtt != null) {
			String value = indentAtt.getNodeValue();
			try {
				indent = Integer.parseInt(value);
			} catch (NumberFormatException e) {
			}
		}
		if (bindentAtt != null) {
			String value = bindentAtt.getNodeValue();
			try {
				bindent = Integer.parseInt(value);
			} catch (NumberFormatException e) {
			}
		}

		BulletParagraph p = new BulletParagraph(addSpace);
		p.setIndent(indent);
		p.setBulletIndent(bindent);
		p.setBulletStyle(style);
		p.setBulletText(text);

		processSegments(p, children, expandURLs);
		return p;
	}

	private void processSegments(Paragraph p, NodeList children,
			boolean expandURLs) {
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			ParagraphSegment segment = null;

			if (child.getNodeType() == Node.TEXT_NODE) {
				String value = getSingleNodeText(child);

				if (value != null && !isIgnorableWhiteSpace(value, false)) {
					p.parseRegularText(value, expandURLs, true,
							getHyperlinkSettings(), null);
				}
			} else if (child.getNodeType() == Node.ELEMENT_NODE) {
				String name = child.getNodeName();
				if (name.equalsIgnoreCase("img")) { //$NON-NLS-1$
					segment = processImageSegment(child);
				} else if (name.equalsIgnoreCase("a")) { //$NON-NLS-1$
					segment = processHyperlinkSegment(child,
							getHyperlinkSettings());
				} else if (name.equalsIgnoreCase("span")) { //$NON-NLS-1$
					processTextSegment(p, expandURLs, child);
				} else if (name.equalsIgnoreCase("b")) { //$NON-NLS-1$
					String text = getNodeText(child);
					String fontId = BOLD_FONT_ID;
					p.parseRegularText(text, expandURLs, true,
							getHyperlinkSettings(), fontId);
				} else if (name.equalsIgnoreCase("br")) { //$NON-NLS-1$
					segment = new BreakSegment();
				} else if (name.equalsIgnoreCase("control")) { //$NON-NLS-1$
					segment = processControlSegment(child);
				}
			}
			if (segment != null) {
				p.addSegment(segment);
			}
		}
	}

	private boolean isIgnorableWhiteSpace(String text, boolean ignoreSpaces) {
		for (int i = 0; i < text.length(); i++) {
			char c = text.charAt(i);
			if (ignoreSpaces && c == ' ')
				continue;
			if (c == '\n' || c == '\r' || c == '\f')
				continue;
			return false;
		}
		return true;
	}

	private ImageSegment processImageSegment(Node image) {
		ImageSegment segment = new ImageSegment();
		processObjectSegment(segment, image, "i."); //$NON-NLS-1$
		return segment;
	}

	private ControlSegment processControlSegment(Node control) {
		ControlSegment segment = new ControlSegment();
		processObjectSegment(segment, control, "o."); //$NON-NLS-1$
		Node fill = control.getAttributes().getNamedItem("fill"); //$NON-NLS-1$
		if (fill!=null) {
			String value = fill.getNodeValue();
			boolean doFill = value.equalsIgnoreCase("true"); //$NON-NLS-1$
			segment.setFill(doFill);
		}
		try {
			Node width = control.getAttributes().getNamedItem("width"); //$NON-NLS-1$
			if (width!=null) {
				String value = width.getNodeValue();
				int doWidth = Integer.parseInt(value);
				segment.setWidth(doWidth);
			}
			Node height = control.getAttributes().getNamedItem("height"); //$NON-NLS-1$
			if (height!=null) {
				String value = height.getNodeValue();
				int doHeight = Integer.parseInt(value);
				segment.setHeight(doHeight);
			}
		}
		catch (NumberFormatException e) {
			// ignore invalid width or height
		}
		return segment;
	}

	private void processObjectSegment(ObjectSegment segment, Node object, String prefix) {
		NamedNodeMap atts = object.getAttributes();
		Node id = atts.getNamedItem("href"); //$NON-NLS-1$
		Node align = atts.getNamedItem("align"); //$NON-NLS-1$
		if (id != null) {
			String value = id.getNodeValue();
			segment.setObjectId(prefix + value);
		}
		if (align != null) {
			String value = align.getNodeValue().toLowerCase();
			if (value.equals("top")) //$NON-NLS-1$
				segment.setVerticalAlignment(ImageSegment.TOP);
			else if (value.equals("middle")) //$NON-NLS-1$
				segment.setVerticalAlignment(ImageSegment.MIDDLE);
			else if (value.equals("bottom")) //$NON-NLS-1$
				segment.setVerticalAlignment(ImageSegment.BOTTOM);
		}
	}

	private void appendText(String value, StringBuffer buf, int[] spaceCounter) {
		if (!whitespaceNormalized)
			buf.append(value);
		else {
			for (int j = 0; j < value.length(); j++) {
				char c = value.charAt(j);
				if (c == ' ' || c == '\t') {
					// space
					if (++spaceCounter[0] == 1) {
						buf.append(c);
					}
				} else if (c == '\n' || c == '\r' || c == '\f') {
					// new line
					if (++spaceCounter[0] == 1) {
						buf.append(' ');
					}
				} else {
					// other characters
					spaceCounter[0] = 0;
					buf.append(c);
				}
			}
		}
	}

	private String getNormalizedText(String text) {
		int[] spaceCounter = new int[1];
		StringBuffer buf = new StringBuffer();

		if (text == null)
			return null;
		appendText(text, buf, spaceCounter);
		return buf.toString();
	}

	private String getSingleNodeText(Node node) {
		return getNormalizedText(node.getNodeValue());
	}

	private String getNodeText(Node node) {
		NodeList children = node.getChildNodes();
		StringBuffer buf = new StringBuffer();
		int[] spaceCounter = new int[1];

		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.TEXT_NODE) {
				String value = child.getNodeValue();
				appendText(value, buf, spaceCounter);
			}
		}
		return buf.toString().trim();
	}

	private ParagraphSegment processHyperlinkSegment(Node link,
			HyperlinkSettings settings) {
		NamedNodeMap atts = link.getAttributes();
		String href = null;
		boolean wrapAllowed = true;
		String boldFontId = null;

		Node hrefAtt = atts.getNamedItem("href"); //$NON-NLS-1$
		if (hrefAtt != null) {
			href = hrefAtt.getNodeValue();
		}
		Node boldAtt = atts.getNamedItem("bold"); //$NON-NLS-1$
		if (boldAtt != null) {
			boldFontId = BOLD_FONT_ID;
		}
		Node nowrap = atts.getNamedItem("nowrap"); //$NON-NLS-1$
		if (nowrap != null) {
			String value = nowrap.getNodeValue();
			if (value != null && value.equalsIgnoreCase("true")) //$NON-NLS-1$
				wrapAllowed = false;
		}
		Object status = checkChildren(link);
		if (status instanceof Node) {
			Node child = (Node)status;
			ImageHyperlinkSegment segment = new ImageHyperlinkSegment();
			segment.setHref(href);
			segment.setWordWrapAllowed(wrapAllowed);
			Node alt = child.getAttributes().getNamedItem("alt"); //$NON-NLS-1$
			if (alt!=null)
				segment.setTooltipText(alt.getNodeValue());
			Node text = child.getAttributes().getNamedItem("text"); //$NON-NLS-1$
			if (text!=null)
				segment.setText(text.getNodeValue());
			processObjectSegment(segment, child, "i."); //$NON-NLS-1$
			return segment;
		}  else if (status instanceof String) {
			String text = (String) status;
			TextHyperlinkSegment segment = new TextHyperlinkSegment(text,
					settings, null);
			segment.setHref(href);
			segment.setFontId(boldFontId);
			Node alt = atts.getNamedItem("alt"); //$NON-NLS-1$
			if (alt!=null)
				segment.setTooltipText(alt.getNodeValue());			
			segment.setWordWrapAllowed(wrapAllowed);
			return segment;
		} else {
			AggregateHyperlinkSegment parent = new AggregateHyperlinkSegment();
			parent.setHref(href);
			NodeList children = link.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node child = children.item(i);
				if (child.getNodeType() == Node.TEXT_NODE) {
					String value = child.getNodeValue();
					TextHyperlinkSegment ts = new TextHyperlinkSegment(
							getNormalizedText(value), settings, null);
					Node alt = atts.getNamedItem("alt"); //$NON-NLS-1$
					if (alt!=null)
						ts.setTooltipText(alt.getNodeValue());
					ts.setWordWrapAllowed(wrapAllowed);
					parent.add(ts);
				} else if (child.getNodeType() == Node.ELEMENT_NODE) {
					String name = child.getNodeName();
					if (name.equalsIgnoreCase("img")) { //$NON-NLS-1$
						ImageHyperlinkSegment is = new ImageHyperlinkSegment();
						processObjectSegment(is, child, "i."); //$NON-NLS-1$
						Node alt = child.getAttributes().getNamedItem("alt"); //$NON-NLS-1$
						if (alt!=null)
							is.setTooltipText(alt.getNodeValue());
						parent.add(is);
						is.setWordWrapAllowed(wrapAllowed);
					}
				}
			}
			return parent;
		}
	}

	private Object checkChildren(Node node) {
		boolean text = false;
		Node imgNode = null;
		//int status = 0;

		NodeList children = node.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.TEXT_NODE)
				text = true;
			else if (child.getNodeType() == Node.ELEMENT_NODE
					&& child.getNodeName().equalsIgnoreCase("img")) { //$NON-NLS-1$
				imgNode = child;
			}
		}
		if (text && imgNode == null)
			return getNodeText(node);
		else if (!text && imgNode != null)
			return imgNode;
		else return null;
	}

	private void processTextSegment(Paragraph p, boolean expandURLs,
			Node textNode) {
		String text = getNodeText(textNode);

		NamedNodeMap atts = textNode.getAttributes();
		Node font = atts.getNamedItem("font"); //$NON-NLS-1$
		Node color = atts.getNamedItem("color"); //$NON-NLS-1$
		boolean wrapAllowed=true;
		Node nowrap = atts.getNamedItem("nowrap"); //$NON-NLS-1$
		if (nowrap != null) {
			String value = nowrap.getNodeValue();
			if (value != null && value.equalsIgnoreCase("true")) //$NON-NLS-1$
				wrapAllowed = false;
		}
		String fontId = null;
		String colorId = null;
		if (font != null) {
			fontId = "f." + font.getNodeValue(); //$NON-NLS-1$
		}
		if (color != null) {
			colorId = "c." + color.getNodeValue(); //$NON-NLS-1$
		}
		p.parseRegularText(text, expandURLs, wrapAllowed, getHyperlinkSettings(), fontId,
				colorId);
	}

	public void parseRegularText(String regularText, boolean convertURLs) {
		reset();

		if (regularText == null)
			return;

		regularText = getNormalizedText(regularText);

		Paragraph p = new Paragraph(true);
		paragraphs.add(p);
		int pstart = 0;

		for (int i = 0; i < regularText.length(); i++) {
			char c = regularText.charAt(i);
			if (p == null) {
				p = new Paragraph(true);
				paragraphs.add(p);
			}
			if (c == '\n') {
				String text = regularText.substring(pstart, i);
				pstart = i + 1;
				p.parseRegularText(text, convertURLs, true, getHyperlinkSettings(),
						null);
				p = null;
			}
		}
		if (p != null) {
			// no new line
			String text = regularText.substring(pstart);
			p.parseRegularText(text, convertURLs, true, getHyperlinkSettings(), null);
		}
	}

	public HyperlinkSettings getHyperlinkSettings() {
		// #132723 cannot have null settings
		if (hyperlinkSettings==null)
			hyperlinkSettings = new HyperlinkSettings(SWTUtil.getStandardDisplay());
		return hyperlinkSettings;
	}

	public void setHyperlinkSettings(HyperlinkSettings settings) {
		this.hyperlinkSettings = settings;
	}

	private void reset() {
		if (paragraphs == null)
			paragraphs = new Vector();
		paragraphs.clear();
		selectedSegmentIndex = -1;
		savedSelectedLinkIndex = -1;
		selectableSegments = null;
	}

	IFocusSelectable[] getFocusSelectableSegments() {
		if (selectableSegments != null || paragraphs == null)
			return selectableSegments;
		Vector result = new Vector();
		for (int i = 0; i < paragraphs.size(); i++) {
			Paragraph p = (Paragraph) paragraphs.get(i);
			ParagraphSegment[] segments = p.getSegments();
			for (int j = 0; j < segments.length; j++) {
				if (segments[j] instanceof IFocusSelectable)
					result.add(segments[j]);
			}
		}
		selectableSegments = (IFocusSelectable[]) result
				.toArray(new IFocusSelectable[result.size()]);
		return selectableSegments;
	}
	
	public IHyperlinkSegment getHyperlink(int index) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		if (selectables.length>index) {
			IFocusSelectable link = selectables[index];
			if (link instanceof IHyperlinkSegment)
				return (IHyperlinkSegment)link;
		}
		return null;
	}
	
	public IHyperlinkSegment findHyperlinkAt(int x, int y) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		for (int i = 0; i < selectables.length; i++) {
			IFocusSelectable segment = selectables[i];
			if (segment instanceof IHyperlinkSegment) {
				IHyperlinkSegment link = (IHyperlinkSegment)segment;
				if (link.contains(x, y))
					return link;
			}
		}
		return null;
	}
	
	public int getHyperlinkCount() {
		return getFocusSelectableSegments().length;
	}
	
	public int indexOf(IHyperlinkSegment link) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		for (int i = 0; i < selectables.length; i++) {
			IFocusSelectable segment = selectables[i];
			if (segment instanceof IHyperlinkSegment) {
				IHyperlinkSegment l = (IHyperlinkSegment)segment;
				if (link==l)
					return i;
			}
		}
		return -1;
	}

	public ParagraphSegment findSegmentAt(int x, int y) {
		for (int i = 0; i < paragraphs.size(); i++) {
			Paragraph p = (Paragraph) paragraphs.get(i);
			ParagraphSegment segment = p.findSegmentAt(x, y);
			if (segment != null)
				return segment;
		}
		return null;
	}
	
	public void clearCache(String fontId) {
		for (int i = 0; i < paragraphs.size(); i++) {
			Paragraph p = (Paragraph) paragraphs.get(i);
			p.clearCache(fontId);
		}
	}

	public IFocusSelectable getSelectedSegment() {
		if (selectableSegments==null || selectedSegmentIndex == -1)
			return null;
		return selectableSegments[selectedSegmentIndex];
	}
	
	public int getSelectedSegmentIndex() {
		return selectedSegmentIndex;
	}
	
	public boolean linkExists(IHyperlinkSegment link) {
		if (selectableSegments==null)
			return false;
		for (int i=0; i<selectableSegments.length; i++) {
			if (selectableSegments[i]==link)
				return true;
		}
		return false;
	}

	public boolean traverseFocusSelectableObjects(boolean next) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		if (selectables == null)
			return false;
		int size = selectables.length;
		if (next) {
			selectedSegmentIndex++;
		} else
			selectedSegmentIndex--;

		if (selectedSegmentIndex < 0 || selectedSegmentIndex > size - 1) {
			selectedSegmentIndex = -1;
		}
		return selectedSegmentIndex != -1;
	}
	
	public IFocusSelectable getNextFocusSegment(boolean next) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		if (selectables == null)
			return null;
		int nextIndex = next?selectedSegmentIndex+1:selectedSegmentIndex-1;

		if (nextIndex < 0 || nextIndex > selectables.length - 1) {
			return null;
		}
		return selectables[nextIndex];
	}
	
	public boolean restoreSavedLink() {
		if (savedSelectedLinkIndex!= -1) {
			selectedSegmentIndex = savedSelectedLinkIndex;
			return true;
		}
		return false;
	}

	public void selectLink(IHyperlinkSegment link) {
		if (link == null) {
			savedSelectedLinkIndex = selectedSegmentIndex;	
			selectedSegmentIndex = -1;
		}
		else {
			select(link);

		}
	}
	
	public void select(IFocusSelectable selectable) {
		IFocusSelectable[] selectables = getFocusSelectableSegments();
		selectedSegmentIndex = -1;
		if (selectables == null)
			return;
		for (int i = 0; i < selectables.length; i++) {
			if (selectables[i].equals(selectable)) {
				selectedSegmentIndex = i;
				break;
			}
		}
	}

	public boolean hasFocusSegments() {
		IFocusSelectable[] segments = getFocusSelectableSegments();
		if (segments.length > 0)
			return true;
		return false;
	}

	public void dispose() {
		paragraphs = null;
		selectedSegmentIndex = -1;
		savedSelectedLinkIndex = -1;
		selectableSegments = null;
	}

	/**
	 * @return Returns the whitespaceNormalized.
	 */
	public boolean isWhitespaceNormalized() {
		return whitespaceNormalized;
	}

	/**
	 * @param whitespaceNormalized
	 *            The whitespaceNormalized to set.
	 */
	public void setWhitespaceNormalized(boolean whitespaceNormalized) {
		this.whitespaceNormalized = whitespaceNormalized;
	}
}
