//------------------------------------------------------------------------
// ZipRC.exe - DtdClassInliner.cs
//
// Licensed under the wxWidgets license, see LICENSE.txt for details.
// (c) Dr. Harald Meyer auf'm Hofe
//
// $Id: DoxygenHtbConverter.cs,v 1.4 2007/10/29 21:14:48 harald_meyer Exp $
//------------------------------------------------------------------------
using System;
using System.Text;
using System.IO;
using System.Collections;
using Contrib.Html;
namespace wx.ZipRC{
/** This class will turn HTML as produced by doxygen into a form that can be displayed by HTB.net.
* Doxygen extensively uses CSS styles and some scripting to make HTML look fancier.
* The corresponding tags and attributes will be ignored by the more simplier wx.HtmlWindow.
* However, this window has the opportunity to integrate widgets and buttons directly using
* special tags. This class uses HtmlParse, a parser specialized for transforming HTML, to
* turn Doxygen comments into an HTB compatible form.
*/
public class DoxygenHtbConverter : HtmlParse
{
TextWriter _dest;
/** Instances of this class will be used either for states as well as properties on the stack.
*/
internal class StateOnStack : ICloneable
{
internal bool ClassTabs = false;
internal bool ClassNav = false;
internal bool IdCurrent = false;
//! This will be loaded with the \c href attribute if present.
internal string HRef = "";
//! This will be loaded with the \c alt attribute if present.
internal string Alt = "";
//! This might be set in the properties to change the font size after ending the tag by a new font tag.
/*! This will be set in the properties to either call for a new font size or mark that
* new font size as set. On the stack this will indicate that earlier tags have set
* this already.
*/
internal int ChangeFontSize = 0;
//! This might be set in the properties to change the font color by a new font tag.
internal string ChangeFontColor = "";
//! This will change bold faces.
internal bool ChangeToBoldface = false;
//! This might be set in the properties to change the font style by a new font tag.
internal bool ChangeToItalics = false;
//! Set an horizontal rule after parsing the end of the element (closing tag).
internal bool SetHorizontalRuleAtEnd = false;
//! if this is not empty, certain end of element tags will generate a choice dialog.
internal IDictionary Choices = new SortedList();
internal StateOnStack() { }
#region ICloneable Member
public object Clone()
{
StateOnStack result = new StateOnStack();
result.ClassTabs = this.ClassTabs;
result.ClassNav = this.ClassNav;
result.IdCurrent = this.IdCurrent;
return result;
}
#endregion
};
/** Generate an instance converting the HTML \c src into an HTML stream to be written to \c dest.
*/
public DoxygenHtbConverter(TextWriter dest, HtmlLex src) : base(src)
{
this._dest = dest;
}
/** Generate an instance converting the HTML \c src into an HTML stream to be written to \c dest.
*/
public DoxygenHtbConverter(TextWriter dest, string src)
: this(dest, new HtmlLex(src))
{
}
/** Generate an instance converting the HTML \c src into an HTML stream to be written to \c dest.
*/
public DoxygenHtbConverter(TextWriter dest, TextReader src)
: this(dest, src.ReadToEnd())
{
}
/** This will be called before any other domain on starting a new element.
*/
protected override void OnStartElementTag(string currentElement)
{
if (this[0].State==null)
this[0].State = new StateOnStack();
this[0].Prop = new StateOnStack();
}
/** Overload this to react on the start of an element.
* \param currentElement is the element's name in lower case letters (e.g. "ul").
* \param currentElementString is the full string describing the current element like for instance '<ul class="test">'.
* \c this[0] will always be this element.
*/
protected override void OnEndElementTag(string currentElement, string tagString, IDictionary attributes)
{
StateOnStack state0 = (StateOnStack)this[0].State;
StateOnStack prop0 = (StateOnStack)this[0].Prop;
if (state0.ClassTabs && currentElement == "ul")
{
// this is the start of the unordered list representing the tabs.
// we will turn this into a table.
// but first, mute the standard output on this element.
this._dest.WriteLine("<table border=1 bgcolor=\"#7085FF\">\n<tr>\n");
}
else if (state0.ClassTabs && currentElement == "li")
{
// this is a list item within the list specifying the tabs. since this
// is turned into a table, this will produce a column. however, tag generation
// has to be delayed since we hae two varients: attribute ID might be "current"
// in that case we will use another background color.
this._dest.Write("<td ");
// this is a list item within the list specifying the tabs. now we have
// all attributes complete. so we can decide now what variant to use.
if (((StateOnStack)this[0].Prop).IdCurrent)
this._dest.Write("bgcolor=\"#E9ECFF\">");
else
this._dest.Write("bgcolor=\"#A6B3FF\">");
}
else if (currentElement == "body")
{
this._dest.Write("<body bgcolor=\"#FFFFFF\" link=\"#334BDA\" alink=\"#F61510\" vlink=\"#F61510\" text=\"#000000\">");
}
else if (currentElement == "area" && prop0.Alt.Length > 0 && prop0.HRef.Length > 0 && this.Depth > 1)
{
((StateOnStack)this[1].Prop).Choices.Add(prop0.Alt, prop0.HRef);
this._dest.Write(tagString);
}
else
this._dest.Write(tagString);
// if the element has been parsed (<token> is the concluding token)
// we might have to add additional tags for instance for setting the font.
// these tags will be closed in OnClosingElement().
if ((prop0.ChangeFontSize != 0 && state0.ChangeFontSize != prop0.ChangeFontSize)
|| (prop0.ChangeFontColor.Length > 0 && state0.ChangeFontColor != prop0.ChangeFontColor))
{
this._dest.Write("<font ");
if (prop0.ChangeFontSize != 0 && state0.ChangeFontSize != prop0.ChangeFontSize)
{
string relative_size = prop0.ChangeFontSize.ToString();
if (prop0.ChangeFontSize > 0)
relative_size = "+" + relative_size;
this._dest.Write("size=\"{0}\" ", relative_size);
state0.ChangeFontSize = prop0.ChangeFontSize;
}
else
prop0.ChangeFontSize = 0;
if (prop0.ChangeFontColor.Length > 0 && state0.ChangeFontColor != prop0.ChangeFontColor)
{
this._dest.Write("color=\"{0}\" ", prop0.ChangeFontColor);
state0.ChangeFontColor = prop0.ChangeFontColor;
}
else
prop0.ChangeFontColor = "";
this._dest.Write(">");
}
else
{
prop0.ChangeFontSize = 0;
prop0.ChangeFontColor = "";
}
if (prop0.ChangeToBoldface)
{
if (state0.ChangeToBoldface)
prop0.ChangeToBoldface = false;
else
this._dest.Write("<b>");
}
if (prop0.ChangeToItalics)
{
if (state0.ChangeToItalics)
prop0.ChangeToItalics = false;
else
this._dest.Write("<i>");
}
}
/** This will be called on defining an attribute of an element.
* \c this[0] will always be the current element. OnElement() has not yet been called.
* The value will be stripped of quotes if necessary.
*/
protected override bool OnAttribute(string attributeName, string value, IDictionary attributes)
{
StateOnStack state0=(StateOnStack)this[0].State;
StateOnStack prop0 = (StateOnStack)this[0].Prop;
if (attributeName == "class")
{
if (value == "tabs")
{
state0.ClassTabs = true;
prop0.ClassTabs = true;
}
else if (value == "nav")
{
state0.ClassNav = true;
prop0.ClassNav = true;
}
else if (value == "memlist")
{
attributes.Add("bgcolor", "#F0F0F0");
}
else if (value == "memItemLeft" || value == "memItemRight"
|| value == "mdescLeft" || value == "mdescRight"
|| value == "memTemplItemLeft" || value == "memTemplItemRight")
{
attributes.Add("bgcolor", "#FAFAFA");
prop0.ChangeToItalics = true;
prop0.ChangeFontSize = -1;
if (value == "memItemLeft")
attributes.Add("align", "right");
if (value == "memItemRight")
attributes.Add("align", "left");
}
else if (value == "memTemplParams")
{
attributes.Add("bgcolor", "#FAFAFA");
prop0.ChangeToItalics = true;
prop0.ChangeFontSize = -1;
prop0.ChangeFontColor = "#606060";
}
else if (value == "tiny")
prop0.ChangeFontSize = -2;
else if (value == "fragment")
{
attributes.Add("bgcolor", "#f5f5f5");
}
else if (value == "groupHeader")
prop0.ChangeToBoldface = true;
else if (value == "indexkey" || value == "indexvalue")
{
attributes.Add("bgcolor", "#E8EEF2");
prop0.ChangeToBoldface = true;
}
else if (value == "keyword")
prop0.ChangeFontColor = "#008000";
else if (value == "keywordtype")
prop0.ChangeFontColor = "#604020";
else if (value == "keywordflow")
prop0.ChangeFontColor = "#e08000";
else if (value == "comment")
prop0.ChangeFontColor = "#800000";
else if (value == "preprocessor")
prop0.ChangeFontColor = "#806020";
else if (value == "stringliteral")
prop0.ChangeFontColor = "#002080";
else if (value == "charliteral")
prop0.ChangeFontColor = "#008080";
else if (value == "dirtab")
{
attributes.Add("bgcolor", "#E8EEF2");
attributes.Add("nowrap", null);
prop0.ChangeToBoldface = true;
}
else if (value == "memname" && this[0].Element == "td")
{
attributes.Add("nowrap", null);
prop0.ChangeFontSize = -1;
prop0.ChangeToBoldface = true;
}
else if (value == "memtemplate")
{
prop0.ChangeFontColor = "#606060";
}
else if (value == "memnav")
{
attributes.Add("align", "center");
attributes.Add("bgcolor", "#E8EEF2");
prop0.ChangeFontSize = -1;
}
else if (value == "memitem")
{
attributes.Add("bgcolor", "#E8F3F5");
prop0.SetHorizontalRuleAtEnd = true;
}
else if (value == "memproto")
{
attributes.Add("bgcolor", "#D5E1E8");
attributes.Add("width", "100%");
}
else if (value == "paramtype")
{
attributes.Add("nowrap", "");
}
else if (value == "paramkey")
{
attributes.Add("align", "right");
}
else if (value == "paramname")
{
attributes.Add("nowrap", "");
attributes.Add("align", "right");
prop0.ChangeFontColor = "#602020";
}
// return false;
}
else if (attributeName == "href")
prop0.HRef = value;
else if (attributeName=="alt")
prop0.Alt = value;
else if (attributeName == "id" && value == "current")
prop0.IdCurrent = true;
return true;
}
/** This will be called whenever the stack decreases.
* \c this[0] is always the \c currentElement.
*/
protected override void OnClosingElement(string currentElement, string tag)
{
StateOnStack state0=(StateOnStack)this[0].State;
StateOnStack prop0 = (StateOnStack)this[0].Prop;
if (state0.ClassTabs && currentElement == "li")
{
// this is a table item
this._dest.WriteLine("</td>");
}
else if (state0.ClassTabs && currentElement == "ul")
// this is a single row within a table
this._dest.WriteLine("</tr>\n</table>");
else
{
if (prop0.ChangeToBoldface)
this._dest.Write("</b>");
if (prop0.ChangeToItalics)
this._dest.Write("</i>");
if (prop0.ChangeFontColor.Length > 0 || prop0.ChangeFontSize != 0)
this._dest.Write("</font>");
this._dest.Write(tag);
if (prop0.Choices.Count > 0)
{
this._dest.WriteLine("\n<choice>");
foreach (DictionaryEntry pair in prop0.Choices)
this._dest.WriteLine("<choice_choice href=\"{1}\" name=\"{0}\">", pair.Key, pair.Value);
this._dest.WriteLine("</choice><hr>");
}
if (prop0.SetHorizontalRuleAtEnd)
this._dest.WriteLine("\n<hr>");
}
}
/** This will be called whenever this is not a part of more specific events.
*/
protected override void OnDefaultEvent(string token)
{
this._dest.Write(token);
}
}
}
|