UWindow
Class UWindowHTMLTextArea

source: e:\games\UnrealTournament\UWindow\Classes\UWindowHTMLTextArea.uc
Core.Object
   |
   +--UWindow.UWindowBase
      |
      +--UWindow.UWindowWindow
         |
         +--UWindow.UWindowDialogControl
            |
            +--UWindow.UWindowDynamicTextArea
               |
               +--UWindow.UWindowHTMLTextArea
Direct Known Subclasses:UBrowserColorIRCTextArea, UBrowserUpdateServerTextArea

class UWindowHTMLTextArea
extends UWindow.UWindowDynamicTextArea


Variables
 Color ALinkColor
 Color BGColor
 float LastBlinkTime
 Color LinkColor
 Color TextColor
 bool bReleased
 bool bShowBlink


Function Summary
 UWindowDynamicTextRow AddText(string NewLine)
 void BeforePaint(Canvas C, float X, float Y)
 float CalcHTMLTextWidth(Canvas C, string Text, out HTMLStyle)
 void Click(float X, float Y)
 float DrawTextLine(Canvas C, UWindowDynamicTextRow L, float Y)
 int FirstMatching(int i, int j)
 int GetHexDigit(string D)
 string GetOption(string HTML, string Option)
 string GetTag(string HTML)
 int GetWrapPos(Canvas C, UWindowDynamicTextRow L, float MaxWidth)
 void HTMLUpdateStyle(string Input, out HTMLStyle)
     
// update the current style based on some text input
 void LaunchUnrealURL(string URL)
 void OverURL(string URL)
 void Paint(Canvas C, float X, float Y)
 Color ParseColor(string S)
 void ParseHTML(string Input, out string, out string, out string)
     
// Get the next HTML tag, the text before it and everthing after it.
 void ProcessInlineHTML(string HTML, out HTMLStyle)
     
// Update CurrentStyle based on the contents of the HTML tag provided
 void ProcessURL(string URL)
 int ReadStyleText(string StyleString, out int, out HTMLStyle)
 void RemoveNextWord(out string, out string)
     
// Find the next word - but don't split up HTML tags.
 void RemoveWrap(UWindowDynamicTextRow L)
 void SetCanvasStyle(Canvas C, HTMLStyle CurrentStyle)
 void SetHTML(string HTML)
 UWindowDynamicTextRow SplitRowAt(UWindowDynamicTextRow L, int SplitPos)
 void TextAreaClipText(Canvas C, float DrawX, float DrawY, string Text, optional bool)
 void TextAreaTextSize(Canvas C, string Text, out float, out float)
 void WrapRow(Canvas C, UWindowDynamicTextRow L)
     
///////////////////////////////////////////////////////
// Overloaded functions from UWindowDynamicTextArea
///////////////////////////////////////////////////////
 string WriteStyleText(HTMLStyle CurrentStyle, int CharCount)



Source Code


00001	class UWindowHTMLTextArea expands UWindowDynamicTextArea;
00002	
00003	/*
00004	
00005	HTML Currently Supported
00006	========================
00007	
00008	Parsed on add
00009	-------------
00010	<body bgcolor=#ffffff link=#ffffff alink=#ffffff>...</body>
00011	<font color=#ffffff bgcolor=#ffffff>...</font>
00012	<br>
00013	<center>....</center>
00014	<p>
00015	<h1>...</h1>
00016	
00017	Parsed on add and display
00018	-------------------------
00019	<nobr>...</nobr>
00020	<a href="...">...</a>
00021	<b>...</b>
00022	<u>...</u>
00023	<blink>...</blink>
00024	
00025	Parsed only on display
00026	----------------------
00027	&gt;
00028	&lt;
00029	&amp;
00030	&nbsp;
00031	
00032	Planned improvements
00033	--------------------
00034	<ul><li>item 1<li>item 2...</ul>
00035	<table>...</table>
00036	
00037	Bugs
00038	----
00039	The parsing is pretty slack!
00040	
00041	*/
00042	
00043	// default styles
00044	var Color TextColor;
00045	var Color BGColor;
00046	var Color LinkColor;
00047	var Color ALinkColor;
00048	var float LastBlinkTime;
00049	var bool bShowBlink;
00050	var bool bReleased;
00051	
00052	function SetHTML(string HTML)
00053	{
00054		Clear();
00055		ReplaceText(HTML, Chr(13)$Chr(10), " ");
00056		ReplaceText(HTML, Chr(13), " ");
00057		ReplaceText(HTML, Chr(10), " ");
00058		AddText(HTML);
00059	}
00060	
00061	function BeforePaint(Canvas C, float X, float Y)
00062	{
00063		Super.BeforePaint(C, X, Y);
00064		Cursor = Root.NormalCursor;
00065	}
00066	
00067	function Paint(Canvas C, float X, float Y)
00068	{
00069		C.DrawColor = BGColor;
00070		DrawStretchedTexture(C, 0, 0, WinWidth, WinHeight, Texture'WhiteTexture');
00071		Super.Paint(C, X, Y);
00072		bReleased = False;
00073	}
00074	
00075	function Click(float X, float Y)
00076	{
00077		Super.Click(X, Y);
00078		bReleased = True;
00079	}
00080	
00081	function ProcessURL(string URL)
00082	{
00083		Log("Clicked Link: >>"$URL$"<<");
00084	
00085		if( Left(URL, 7) ~= "mailto:" )
00086			GetPlayerOwner().ConsoleCommand("start "$URL);
00087		if( Left(URL, 7) ~= "http://" )
00088			GetPlayerOwner().ConsoleCommand("start "$URL);
00089		if( Left(URL, 6) ~= "ftp://" )
00090			GetPlayerOwner().ConsoleCommand("start "$URL);
00091		if( Left(URL, 9) ~= "telnet://" )
00092			GetPlayerOwner().ConsoleCommand("start "$URL);
00093		if( Left(URL, 9) ~= "gopher://" )
00094			GetPlayerOwner().ConsoleCommand("start "$URL);
00095		if( Left(URL, 4) ~= "www." )
00096			GetPlayerOwner().ConsoleCommand("start http://"$URL);
00097		if( Left(URL, 4) ~= "ftp." )
00098			GetPlayerOwner().ConsoleCommand("start ftp://"$URL);
00099		else
00100		if( Left(URL, 9) ~= "unreal://" )
00101			LaunchUnrealURL(URL);
00102	}
00103	
00104	function OverURL(string URL)
00105	{
00106	}
00107	
00108	function LaunchUnrealURL(string URL)
00109	{
00110		GetPlayerOwner().ClientTravel(URL, TRAVEL_Absolute, false);
00111	}
00112	
00113	function TextAreaTextSize(Canvas C, string Text, out float W, out float H)
00114	{
00115		ReplaceText(Text, "&nbsp;", " ");
00116		ReplaceText(Text, "&gt;", ">");
00117		ReplaceText(Text, "&lt;", "<");
00118		ReplaceText(Text, "&amp;", "&");
00119	
00120		TextSize(C, Text, W, H);
00121	}
00122	
00123	function TextAreaClipText(Canvas C, float DrawX, float DrawY, coerce string Text, optional bool bCheckHotkey)
00124	{
00125		ReplaceText(Text, "&nbsp;", " ");
00126		ReplaceText(Text, "&gt;", ">");
00127		ReplaceText(Text, "&lt;", "<");
00128		ReplaceText(Text, "&amp;", "&");
00129	
00130		ClipText(C, DrawX, DrawY, Text, bCheckHotKey);
00131	}
00132	
00133	///////////////////////////////////////////////////////
00134	// Overloaded functions from UWindowDynamicTextArea
00135	///////////////////////////////////////////////////////
00136	
00137	function WrapRow(Canvas C, UWindowDynamicTextRow L)
00138	{
00139		local HTMLStyle CurrentStyle;
00140		local UWindowHTMLTextRow R;
00141		local string Input, LeftText, HTML, RightText;
00142	
00143		Super.WrapRow(C, L);
00144	
00145		// Generate the DisplayString and StyleString lines for each row
00146		R = UWindowHTMLTextRow(L);
00147		while(R != None && (R == L || R.WrapParent == L))
00148		{
00149			R.DisplayString = "";
00150			R.StyleString = "";
00151	
00152			CurrentStyle = R.StartStyle;
00153			
00154			Input = R.Text;
00155			while(Input != "")
00156			{
00157				ParseHTML(Input, LeftText, HTML, RightText);
00158	
00159				if(LeftText != "" || R.DisplayString == "")
00160				{
00161					R.DisplayString = R.DisplayString $ LeftText;
00162					R.StyleString = R.StyleString $ WriteStyleText(CurrentStyle, Len(LeftText));
00163				}
00164	
00165				ProcessInlineHTML(HTML, CurrentStyle);
00166				SetCanvasStyle(C, CurrentStyle);
00167	
00168				Input = RightText;
00169			}
00170	
00171			R = UWindowHTMLTextRow(R.Next);
00172		}	
00173	}
00174	
00175	function float DrawTextLine(Canvas C, UWindowDynamicTextRow L, float Y)
00176	{
00177		local float X, W, H, MouseX, MouseY;
00178		local HTMLStyle CurrentStyle;
00179		local float RowHeight;
00180		local Color OldColor;
00181		local int StylePos, DisplayPos, i;
00182		local string S;
00183	
00184		RowHeight = 0;
00185	
00186		CurrentStyle = UWindowHTMLTextRow(L).StartStyle;
00187		if(CurrentStyle.bCenter)
00188		{
00189			W = CalcHTMLTextWidth(C, L.Text, CurrentStyle);
00190			if(VertSB.bWindowVisible)
00191				X = int(((WinWidth - VertSB.WinWidth) - W) / 2);
00192			else
00193				X = int((WinWidth - W) / 2);
00194		}
00195		else
00196			X = 2;
00197	
00198		if(GetEntryLevel().TimeSeconds > LastBlinkTime + 0.5)
00199		{
00200			bShowBlink = !bShowBlink;
00201			LastBlinkTime = GetEntryLevel().TimeSeconds;
00202		}
00203	
00204		if(UWindowHTMLTextRow(L).DisplayString == "")
00205			SetCanvasStyle(C, CurrentStyle);
00206		else
00207		{
00208			while(DisplayPos < Len(UWindowHTMLTextRow(L).DisplayString))
00209			{
00210				i = ReadStyleText(UWindowHTMLTextRow(L).StyleString, StylePos, CurrentStyle);
00211				S = Mid(UWindowHTMLTextRow(L).DisplayString, DisplayPos, i);
00212				DisplayPos += i;					
00213				SetCanvasStyle(C, CurrentStyle);
00214	
00215				TextAreaTextSize(C, S, W, H);
00216				if(H > RowHeight)
00217					RowHeight = H;
00218	
00219				if(CurrentStyle.bLink)
00220				{
00221					GetMouseXY(MouseX, MouseY);
00222					if(X < MouseX && X + W > MouseX && Y < MouseY && Y + H > MouseY)
00223					{
00224						Cursor = Root.HandCursor;
00225						OverURL(CurrentStyle.LinkDestination);
00226	
00227						if(bMouseDown || bReleased)
00228						{
00229							if(bReleased)
00230							{
00231								ProcessURL(CurrentStyle.LinkDestination);
00232								bReleased = False;
00233							}
00234							else
00235								C.DrawColor = ALinkColor;
00236						}
00237					}
00238				}
00239	
00240				if(CurrentStyle.BGColor != BGColor)
00241				{	
00242					OldColor = C.DrawColor;
00243					C.DrawColor = CurrentStyle.BGColor;
00244					DrawStretchedTexture(C, X, Y, W, H, Texture'WhiteTexture');
00245					C.DrawColor = OldColor;
00246				}
00247				if(!CurrentStyle.bBlink || bShowBlink)
00248					TextAreaClipText(C, X, Y, S);
00249				if(CurrentStyle.bLink || CurrentStyle.bUnderline)
00250					DrawStretchedTexture(C, X, Y+H-1, W, 1, Texture'WhiteTexture');
00251	
00252				X += W;
00253			}
00254		}
00255		if(RowHeight == 0)
00256			TextAreaTextSize(C, "A", W, RowHeight);
00257	
00258		return RowHeight;
00259	}
00260	
00261	function UWindowDynamicTextRow SplitRowAt(UWindowDynamicTextRow L, int SplitPos)
00262	{
00263		local UWindowDynamicTextRow N;
00264		local HTMLStyle CurrentStyle;
00265	
00266		N = Super.SplitRowAt(L, SplitPos);
00267	
00268		// update the style by processing from the start of L to the split position.
00269		UWindowHTMLTextRow(N).EndStyle = UWindowHTMLTextRow(L).EndStyle;
00270		CurrentStyle = UWindowHTMLTextRow(L).StartStyle;
00271		HTMLUpdateStyle(L.Text, CurrentStyle);
00272		UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00273		UWindowHTMLTextRow(N).StartStyle = CurrentStyle;
00274	
00275		return N;
00276	}
00277	
00278	function RemoveWrap(UWindowDynamicTextRow L)
00279	{
00280		local UWindowDynamicTextRow N;
00281	
00282		// copy final endstyle to current row
00283		N = UWindowDynamicTextRow(L.Next);
00284		while(N != None && N.WrapParent == L)
00285		{
00286			UWindowHTMLTextRow(L).EndStyle = UWindowHTMLTextRow(N).EndStyle;
00287			N = UWindowDynamicTextRow(N.Next);
00288		}
00289	
00290		Super.RemoveWrap(L);
00291	}
00292	
00293	function int GetWrapPos(Canvas C, UWindowDynamicTextRow L, float MaxWidth)
00294	{
00295		local float W, LineWidth, NextWordWidth;
00296		local string Input, NextWord;
00297		local int WordsThisRow, WrapPos;
00298		local HTMLStyle CurrentStyle;
00299	
00300		CurrentStyle = UWindowHTMLTextRow(L).StartStyle;
00301	
00302		// quick check
00303		if(CalcHTMLTextWidth(C, L.Text, CurrentStyle) <= MaxWidth)
00304			return -1;
00305	
00306		Input = L.Text;
00307		WordsThisRow = 0;
00308		LineWidth = 0;
00309		WrapPos = 0;
00310		NextWord = "";
00311		CurrentStyle = UWindowHTMLTextRow(L).StartStyle;
00312	
00313		while(Input != "" || NextWord != "")
00314		{
00315			if(NextWord == "")
00316			{
00317				RemoveNextWord(Input, NextWord);
00318				NextWordWidth = CalcHTMLTextWidth(C, NextWord, CurrentStyle);
00319			}
00320			if(WordsThisRow > 0 && LineWidth + NextWordWidth > MaxWidth)
00321			{
00322				return WrapPos;
00323			}
00324			else
00325			{
00326				WrapPos += Len(NextWord);
00327				LineWidth += NextWordWidth;
00328				NextWord = "";
00329				WordsThisRow++;
00330			}
00331		}
00332		return -1;
00333	}
00334	
00335	// Find the next word - but don't split up HTML tags.
00336	function RemoveNextWord(out string Text, out string NextWord)
00337	{
00338		local int i;
00339		local bool bInsideTag;
00340		local string Ch;
00341		
00342		bInsideTag = False;
00343	
00344		for(i=0;i<Len(Text);i++)
00345		{
00346			Ch = Mid(Text, i, 1);
00347			if(Ch == ">")
00348				bInsideTag = False;
00349			if(Ch == "<")
00350				bInsideTag = True;
00351			if(Ch == " " && !bInsideTag)
00352				break;
00353		}
00354		while(Mid(Text, i, 1) == " ")
00355			i++;	
00356		NextWord = Left(Text, i);
00357		Text = Mid(Text, i);
00358	}
00359	
00360	function UWindowDynamicTextRow AddText(string NewLine)
00361	{
00362		local string Input, Output, LeftText, RightText, HTML, Temp;
00363		local int i;
00364		local UWindowDynamicTextRow L;
00365		local HTMLStyle CurrentStyle, StartStyle;
00366	
00367		if(List.Last == List)
00368		{
00369			CurrentStyle.BulletLevel = 0;
00370			CurrentStyle.LinkDestination = "";
00371			CurrentStyle.TextColor = TextColor;
00372			CurrentStyle.BGColor = BGColor;
00373			CurrentStyle.bCenter = bHCenter;
00374			CurrentStyle.bLink = False;
00375			CurrentStyle.bUnderline = False;
00376			CurrentStyle.bNoBR = False;
00377			CurrentStyle.bHeading = False;
00378			CurrentStyle.bBold = False;
00379			CurrentStyle.bBlink = False;
00380		}
00381		else
00382			CurrentStyle = UWindowHTMLTextRow(List.Last).EndStyle;
00383		StartStyle = CurrentStyle;
00384	
00385		// convert \\n's -> <br>'s
00386		i = InStr(NewLine, "\\n");
00387		while(i != -1)
00388		{
00389			NewLine = Left(NewLine, i) $ "<br>" $ Mid(NewLine, i + 2);
00390			i = InStr(NewLine, "\\n");
00391		}
00392	
00393		Input = NewLine;
00394		Output = "";
00395		while(Input != "")
00396		{
00397			ParseHTML(Input, LeftText, HTML, RightText);
00398			
00399			switch(GetTag(HTML))
00400			{
00401			// multiline HTML tags
00402			case "P":
00403				if((Output $ LeftText) != "")
00404				{
00405					L = Super.AddText(Output $ LeftText);
00406					Output = "";
00407					UWindowHTMLTextRow(L).StartStyle = StartStyle;
00408					UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00409				}
00410				StartStyle = CurrentStyle;
00411				L = Super.AddText("");
00412				UWindowHTMLTextRow(L).StartStyle = StartStyle;
00413				UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00414				break;
00415			case "BR":
00416				L = Super.AddText(Output $ LeftText);
00417				Output = "";
00418				UWindowHTMLTextRow(L).StartStyle = StartStyle;
00419				UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00420				StartStyle = CurrentStyle;
00421				break;
00422			case "BODY":
00423				Temp = GetOption(HTML, "BGCOLOR=");
00424				if(Temp != "")
00425				{
00426					BGColor = ParseColor(Temp);
00427					CurrentStyle.BGColor = BGColor;
00428					StartStyle.BGColor = BGColor;
00429				}
00430	
00431				Temp = GetOption(HTML, "LINK=");
00432				if(Temp != "")
00433					LinkColor = ParseColor(Temp);
00434	
00435				Temp = GetOption(HTML, "ALINK=");
00436				if(Temp != "")
00437					ALinkColor = ParseColor(Temp);
00438	
00439				Temp = GetOption(HTML, "TEXT=");
00440				if(Temp != "")
00441				{
00442					TextColor = ParseColor(Temp);
00443					CurrentStyle.TextColor = TextColor;
00444				}
00445				Output = Output $ LeftText;
00446				break;
00447			case "CENTER":
00448				if((Output $ LeftText) != "")
00449				{
00450					L = Super.AddText(Output $ LeftText);
00451					Output = "";
00452					UWindowHTMLTextRow(L).StartStyle = StartStyle;
00453					UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00454				}
00455				CurrentStyle.bCenter = True;
00456				StartStyle = CurrentStyle;
00457				break;
00458			case "/CENTER":
00459				L = Super.AddText(Output $ LeftText);
00460				Output = "";
00461				UWindowHTMLTextRow(L).StartStyle = StartStyle;
00462				UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00463				CurrentStyle.bCenter = False;
00464				StartStyle = CurrentStyle;
00465				break;			
00466			// Inline HTML tags
00467			case "H1":
00468				if((Output $ LeftText) != "")
00469				{
00470					L = Super.AddText(Output $ LeftText);
00471					Output = "";
00472					UWindowHTMLTextRow(L).StartStyle = StartStyle;
00473					UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00474				}
00475				CurrentStyle.bHeading = True;
00476				StartStyle = CurrentStyle;
00477				break;
00478			case "/H1":
00479				L = Super.AddText(Output $ LeftText);
00480				Output = "";
00481				UWindowHTMLTextRow(L).StartStyle = StartStyle;
00482				UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00483				CurrentStyle.bHeading = False;
00484				StartStyle = CurrentStyle;
00485				break;			
00486			case "FONT":
00487				Output = Output $ LeftText $ HTML;
00488				Temp = GetOption(HTML, "COLOR=");
00489				if(Temp != "")
00490					CurrentStyle.TextColor = ParseColor(Temp);
00491				Temp = GetOption(HTML, "BGCOLOR=");
00492				if(Temp != "")
00493					CurrentStyle.BGColor = ParseColor(Temp);
00494				break;
00495			case "/FONT":
00496				Output = Output $ LeftText $ HTML;
00497				CurrentStyle.TextColor = TextColor;
00498				CurrentStyle.BGColor = BGColor;
00499				break;
00500			case "B":
00501				Output = Output $ LeftText $ HTML;
00502				CurrentStyle.bBold = True;
00503				break;
00504			case "/B":
00505				Output = Output $ LeftText $ HTML;
00506				CurrentStyle.bBold = False;
00507				break;
00508			case "U":
00509				Output = Output $ LeftText $ HTML;
00510				CurrentStyle.bUnderline = True;
00511				break;
00512			case "/U":
00513				Output = Output $ LeftText $ HTML;
00514				CurrentStyle.bUnderline = False;
00515				break;
00516			case "A":
00517				Output = Output $ LeftText $ HTML;
00518				CurrentStyle.bLink = True;
00519				CurrentStyle.LinkDestination = GetOption(HTML, "HREF=");
00520				break;
00521			case "/A":
00522				Output = Output $ LeftText $ HTML;
00523				CurrentStyle.bLink = False;
00524				CurrentStyle.LinkDestination = "";
00525				break;
00526			case "NOBR":
00527				Output = Output $ LeftText $ HTML;
00528				CurrentStyle.bNoBR = True;
00529				break;
00530			case "/NOBR":
00531				Output = Output $ LeftText $ HTML;
00532				CurrentStyle.bNoBR = False;
00533				break;
00534			case "BLINK":
00535				Output = Output $ LeftText $ HTML;
00536				CurrentStyle.bBlink = True;
00537				break;
00538			case "/BLINK":
00539				Output = Output $ LeftText $ HTML;
00540				CurrentStyle.bBlink = False;
00541				break;
00542			default:
00543				Output = Output $ LeftText;
00544				break;
00545			}
00546			Input = RightText;
00547		}
00548	
00549		L = Super.AddText(Output);
00550		UWindowHTMLTextRow(L).StartStyle = StartStyle;
00551		UWindowHTMLTextRow(L).EndStyle = CurrentStyle;
00552	
00553		return L;
00554	}
00555	
00556	///////////////////////////////////////////////////
00557	// HTML Text Processing
00558	///////////////////////////////////////////////////
00559	
00560	// Get the next HTML tag, the text before it and everthing after it.
00561	function ParseHTML(string Input, out string LeftText, out string HTML, out string RightText)
00562	{
00563		local int i;
00564		
00565		i = InStr(Input, "<");
00566		if(i == -1)
00567		{
00568			LeftText = Input;
00569			HTML = "";
00570			RightText = "";
00571			return;
00572		}
00573	
00574		LeftText = Left(Input, i);
00575		HTML = Mid(Input, i);
00576	
00577		i = InStr(HTML, ">");
00578		if(i == -1)
00579		{
00580			RightText = "";
00581			return;
00582		}
00583	
00584		RightText = Mid(HTML, i+1);
00585		HTML = Left(HTML, i+1);	
00586	}
00587	
00588	function float CalcHTMLTextWidth(Canvas C, string Text, out HTMLStyle CurrentStyle)
00589	{
00590		local string Input, LeftText, HTML, RightText;
00591		local float W, H, Width;
00592	
00593		Width = 0;
00594		Input = Text;
00595		while(Input != "")
00596		{
00597			ParseHTML(Input, LeftText, HTML, RightText);
00598	
00599			SetCanvasStyle(C, CurrentStyle);
00600			TextAreaTextSize(C, LeftText, W, H);
00601			Width += W;
00602						
00603			ProcessInlineHTML(HTML, CurrentStyle);
00604	
00605			Input = RightText;
00606		}
00607	
00608		return Width;
00609	}
00610	
00611	// Update CurrentStyle based on the contents of the HTML tag provided
00612	function ProcessInlineHTML(string HTML, out HTMLStyle CurrentStyle)
00613	{
00614		local string Temp;
00615	
00616		if(HTML == "")	
00617			return;
00618	
00619		switch(GetTag(HTML))
00620		{
00621		case "H1":
00622			CurrentStyle.bHeading = True;
00623			break;
00624		case "/H1":
00625			CurrentStyle.bHeading = False;
00626			break;			
00627		case "FONT":
00628			Temp = GetOption(HTML, "COLOR=");
00629			if(Temp != "")
00630				CurrentStyle.TextColor = ParseColor(Temp);
00631			Temp = GetOption(HTML, "BGCOLOR=");
00632			if(Temp != "")
00633				CurrentStyle.BGColor = ParseColor(Temp);
00634			break;
00635		case "/FONT":
00636			CurrentStyle.TextColor = TextColor;
00637			CurrentStyle.BGColor = BGColor;
00638			break;
00639		case "B":
00640			CurrentStyle.bBold = True;
00641			break;
00642		case "/B":
00643			CurrentStyle.bBold = False;
00644			break;
00645		case "U":
00646			CurrentStyle.bUnderline = True;
00647			break;
00648		case "/U":
00649			CurrentStyle.bUnderline = False;
00650			break;
00651		case "A":
00652			CurrentStyle.bLink = True;
00653			CurrentStyle.LinkDestination = GetOption(HTML, "HREF=");
00654			break;
00655		case "/A":
00656			CurrentStyle.bLink = False;
00657			CurrentStyle.LinkDestination = "";
00658			break;
00659		case "NOBR":
00660			CurrentStyle.bNoBR = True;
00661			break;
00662		case "/NOBR":
00663			CurrentStyle.bNoBR = False;
00664			break;
00665		case "BLINK":
00666			CurrentStyle.bBlink = True;
00667			break;
00668		case "/BLINK":
00669			CurrentStyle.bBlink = False;
00670			break;
00671		}
00672	}
00673	
00674	// update the current style based on some text input
00675	function HTMLUpdateStyle(string Input, out HTMLStyle CurrentStyle)
00676	{
00677		local string LeftText, HTML, RightText; 
00678	
00679		while(Input != "")
00680		{
00681			ParseHTML(Input, LeftText, HTML, RightText);
00682			ProcessInlineHTML(HTML, CurrentStyle);
00683			Input = RightText;
00684		}
00685	}
00686	
00687	function string GetOption(string HTML, string Option)
00688	{
00689		local int i, j;
00690		local string s;
00691		
00692		i = InStr(Caps(HTML), Caps(Option));
00693	
00694		if(i == 1 || Mid(HTML, i-1, 1) == " ") 
00695		{
00696			s = Mid(HTML, i+Len(Option));
00697			j = FirstMatching(InStr(s, ">"), InStr(s, " "));
00698			s = Left(s, j);
00699	
00700			if(Left(s, 1) == "\"")
00701				s = Mid(s, 1);
00702	
00703			if(Right(s, 1) == "\"")
00704				s = Left(s, Len(s) - 1);
00705	
00706			return s;
00707		}
00708		return "";
00709	}
00710	
00711	function string GetTag(string HTML)
00712	{
00713		local int i;
00714	
00715		if(HTML == "")
00716			return "";
00717	
00718		HTML = Mid(HTML, 1); // lose <
00719	
00720		i = FirstMatching(InStr(HTML, ">"), InStr(HTML, " "));
00721		if(i == -1)
00722			return Caps(HTML);
00723		else
00724			return Caps(Left(HTML, i));
00725	}
00726	
00727	function Color ParseColor(string S)
00728	{
00729		local Color C;
00730	
00731		if(Left(S, 1) == "#")
00732			S = Mid(S, 1);
00733	
00734		C.R = 16 * GetHexDigit(Mid(S, 0, 1)) + GetHexDigit(Mid(S, 1, 1));
00735		C.G = 16 * GetHexDigit(Mid(S, 2, 1)) + GetHexDigit(Mid(S, 3, 1));
00736		C.B = 16 * GetHexDigit(Mid(S, 4, 1)) + GetHexDigit(Mid(S, 5, 1));
00737	
00738		return C;
00739	}
00740	
00741	function int GetHexDigit(string D)
00742	{
00743		switch(caps(D))
00744		{
00745		case "0": return 0;
00746		case "1": return 1;
00747		case "2": return 2;
00748		case "3": return 3;
00749		case "4": return 4;
00750		case "5": return 5; 
00751		case "6": return 6; 
00752		case "7": return 7; 
00753		case "8": return 8; 
00754		case "9": return 9; 
00755		case "A": return 10; 
00756		case "B": return 11; 
00757		case "C": return 12; 
00758		case "D": return 13; 
00759		case "E": return 14; 
00760		case "F": return 15; 
00761		}
00762	
00763		return 0;
00764	}
00765	
00766	function int FirstMatching(int i, int j)
00767	{
00768		if(i == -1)
00769			return j;
00770	
00771		if(j == -1)
00772			return i;
00773		else
00774			return Min(i, j);
00775	}
00776	
00777	function SetCanvasStyle(Canvas C, HTMLStyle CurrentStyle)
00778	{
00779		if(CurrentStyle.bLink)
00780			C.DrawColor = LinkColor;
00781		else
00782			C.DrawColor = CurrentStyle.TextColor;
00783	
00784		if(CurrentStyle.bHeading)
00785			C.Font = Root.Fonts[F_LargeBold];
00786		else
00787		if(CurrentStyle.bBold)
00788			C.Font = Root.Fonts[F_Bold];
00789		else
00790			C.Font = Root.Fonts[F_Normal];
00791	}
00792	
00793	function string WriteStyleText(HTMLStyle CurrentStyle, int CharCount)
00794	{
00795		local string Pad;
00796		local string Temp;
00797		local string Output;
00798	
00799		Pad = "0000";
00800	
00801		Temp = string(CharCount);
00802		Output = Left(Pad, 4 - Len(Temp)) $ Temp;
00803			
00804		Temp = string(Len(CurrentStyle.LinkDestination));
00805		Output = Output $ Left(Pad, 4 - Len(Temp)) $ Temp $ CurrentStyle.LinkDestination;
00806	
00807		Temp = string(CurrentStyle.TextColor.R);
00808		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00809		Temp = string(CurrentStyle.TextColor.G);
00810		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00811		Temp = string(CurrentStyle.TextColor.B);
00812		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00813	
00814		Temp = string(CurrentStyle.BGColor.R);
00815		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00816		Temp = string(CurrentStyle.BGColor.G);
00817		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00818		Temp = string(CurrentStyle.BGColor.B);
00819		Output = Output $ Left(Pad, 3 - Len(Temp)) $ Temp;
00820	
00821		if(CurrentStyle.bCenter)
00822			Output = Output $ "T";
00823		else
00824			Output = Output $ "F";
00825	
00826		if(CurrentStyle.bLink)
00827			Output = Output $ "T";
00828		else
00829			Output = Output $ "F";
00830	
00831		if(CurrentStyle.bUnderline)
00832			Output = Output $ "T";
00833		else
00834			Output = Output $ "F";
00835	
00836		if(CurrentStyle.bNoBR)
00837			Output = Output $ "T";
00838		else
00839			Output = Output $ "F";
00840	
00841		if(CurrentStyle.bHeading)
00842			Output = Output $ "T";
00843		else
00844			Output = Output $ "F";
00845	
00846		if(CurrentStyle.bBold)
00847			Output = Output $ "T";
00848		else
00849			Output = Output $ "F";
00850	
00851		if(CurrentStyle.bBlink)
00852			Output = Output $ "T";
00853		else
00854			Output = Output $ "F";
00855	
00856		return Output;
00857	}
00858	
00859	function int ReadStyleText(string StyleString, out int StylePos, out HTMLStyle CurrentStyle)
00860	{
00861		local string Temp;
00862		local int CharCount;
00863		local int i;	
00864	
00865		CharCount = Int(Mid(StyleString, StylePos, 4));
00866		StylePos += 4;
00867	
00868		i = Int(Mid(StyleString, StylePos, 4));
00869		StylePos += 4;
00870			
00871		CurrentStyle.LinkDestination = Mid(StyleString, StylePos, i);
00872		StylePos += i;
00873	
00874		CurrentStyle.TextColor.R = Int(Mid(StyleString, StylePos, 3));
00875		StylePos += 3;
00876		CurrentStyle.TextColor.G = Int(Mid(StyleString, StylePos, 3));
00877		StylePos += 3;
00878		CurrentStyle.TextColor.B = Int(Mid(StyleString, StylePos, 3));
00879		StylePos += 3;
00880	
00881		CurrentStyle.BGColor.R = Int(Mid(StyleString, StylePos, 3));
00882		StylePos += 3;
00883		CurrentStyle.BGColor.G = Int(Mid(StyleString, StylePos, 3));
00884		StylePos += 3;
00885		CurrentStyle.BGColor.B = Int(Mid(StyleString, StylePos, 3));
00886		StylePos += 3;
00887	
00888		CurrentStyle.bCenter = Mid(StyleString, StylePos++, 1) == "T";
00889		CurrentStyle.bLink = Mid(StyleString, StylePos++, 1) == "T";
00890		CurrentStyle.bUnderline = Mid(StyleString, StylePos++, 1) == "T";
00891		CurrentStyle.bNoBR = Mid(StyleString, StylePos++, 1) == "T";
00892		CurrentStyle.bHeading = Mid(StyleString, StylePos++, 1) == "T";
00893		CurrentStyle.bBold = Mid(StyleString, StylePos++, 1) == "T";
00894		CurrentStyle.bBlink = Mid(StyleString, StylePos++, 1) == "T";
00895	
00896		return CharCount;
00897	}
00898	
00899	defaultproperties
00900	{
00901	     TextColor=(R=255,G=255,B=255)
00902	     LinkColor=(B=255)
00903	     ALinkColor=(R=255)
00904	     bTopCentric=True
00905	     bAutoScrollbar=True
00906	     bVariableRowHeight=True
00907	     RowClass=Class'UWindow.UWindowHTMLTextRow'
00908	     bIgnoreLDoubleClick=True
00909	}

End Source Code