MODULE WebBrowserPanel;
IMPORT
HTMLScanner, HTMLParser, HTMLTransformer, WebBrowserComponents,
WMComponents, WMProperties, WMTextView, WMStandardComponents, Texts, WMEvents, TextUtilities,
Codecs, XML, XMLObjects, Strings, KernelLog, Messages := WMMessages;
CONST
verbose = TRUE;
modeSourceCode = 0;
modeParsedHtml = 1;
modeBbtXml = 2;
modeBbtText = 3;
outputMode = modeBbtText;
typePercent = 0;
typeParts = 1;
typeFix = 2;
TYPE
String = Strings.String;
VisualComponent = WMComponents.VisualComponent;
NotifyMsg* = POINTER TO RECORD
url* : String;
title* : String;
loadID* : LONGINT;
END;
LoadedMsg* = POINTER TO RECORD
vc : VisualComponent;
url : String;
title : String;
END;
FrameNode = POINTER TO RECORD
next : FrameNode;
name : String;
scrolling : BOOLEAN;
size : LONGINT;
relative : BOOLEAN;
panel : VisualComponent;
isLast : BOOLEAN;
END;
FrameslotNode = POINTER TO RECORD
next : FrameslotNode;
size : LONGINT;
type : LONGINT;
END;
FramesetNode = POINTER TO RECORD
next : FramesetNode;
frameset : XML.Element;
src : String;
name : String;
scrolling : BOOLEAN;
END;
WebPanel* = OBJECT (VisualComponent)
VAR
url- : WMProperties.StringProperty;
notify* : WMEvents.EventListener;
openNewWindow* : PROCEDURE {DELEGATE} (url : String);
loadLink* : WMEvents.EventListener;
vc : VisualComponent;
loadingText : WebBrowserComponents.ShortText;
pending : BOOLEAN;
loadID : LONGINT;
PROCEDURE &Init*;
VAR
s : String;
BEGIN
Init^;
takesFocus.Set(FALSE);
NEW(url, NIL, Strings.NewString("WebPanel URL"), Strings.NewString("Stores the URL of a WebPanel"));
s := Strings.NewString(" Loading...");
NEW(loadingText, s^);
pending := FALSE;
END Init;
PROCEDURE Load*(loadID : LONGINT);
VAR
cl : ContentLoader;
BEGIN
IF ~pending THEN
pending := TRUE;
SELF.loadID := loadID;
IF vc # NIL THEN
RemoveContent(vc);
END;
AddContent(loadingText);
Reset(SELF, NIL);
AlignSubComponents();
Invalidate();
NEW(cl, SELF);
END;
END Load;
PROCEDURE Loaded(sender, data : ANY);
VAR
msg : LoadedMsg;
notifyMsg : NotifyMsg;
BEGIN
IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Loaded, sender, data)
ELSE
RemoveContent(loadingText);
msg := data(LoadedMsg);
vc := msg.vc;
AddContent(vc);
NEW(notifyMsg);
notifyMsg.url := msg.url;
notifyMsg.title := msg.title;
notifyMsg.loadID := loadID;
notify(SELF, notifyMsg);
Reset(SELF, NIL);
AlignSubComponents();
Invalidate();
pending := FALSE;
END;
END Loaded;
PROCEDURE LoadLink(sender, data : ANY);
VAR
link, target : String;
targetLow : String;
BEGIN
IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.LoadLink, sender, data)
ELSE
DecodeLinkData(data, link, target);
IF Strings.StartsWith2("#", link^) THEN
ELSE
targetLow := Strings.LowerCaseInNew(target^);
IF (target^ = "") OR (targetLow^ = "_self") OR (targetLow^ = "_top") OR (targetLow^ = "_parent") THEN
IF loadLink # NIL THEN
loadLink(SELF, data);
ELSE
url.Set(link);
Load(-1);
END;
ELSE
IF openNewWindow # NIL THEN
openNewWindow(link);
END;
END;
END;
END;
END LoadLink;
END WebPanel;
ContentLoader = OBJECT
VAR
webPanel : WebPanel;
msg : LoadedMsg;
vc : VisualComponent;
url : String;
title : String;
PROCEDURE &New*(webPanel : WebPanel);
BEGIN
SELF.webPanel := webPanel;
END New;
BEGIN {ACTIVE}
NEW(msg);
msg.url := webPanel.url.Get();
IF verbose THEN KernelLog.String("ContentLoader: Loading: "); KernelLog.String(msg.url^); KernelLog.Ln; END;
msg.vc := GetContent(msg.url, msg.title, webPanel.bounds.GetWidth(), webPanel.bounds.GetHeight(), TRUE, webPanel.LoadLink, NIL);
webPanel.Loaded(SELF, msg);
IF verbose THEN KernelLog.String("ContentLoader: Loading done."); KernelLog.Ln; END;
END ContentLoader;
HTMLPanel = OBJECT (VisualComponent)
VAR
rc : WebBrowserComponents.ResourceConnection;
width : LONGINT;
height : LONGINT;
scrollbars : BOOLEAN;
loadLink : WMEvents.EventListener;
charset : String;
frameName : String;
firstResize : BOOLEAN;
tv : WMTextView.TextView;
text : Texts.Text;
blankText : Texts.Text;
vScrollbar : WMStandardComponents.Scrollbar;
hScrollbar : WMStandardComponents.Scrollbar;
scanner : HTMLScanner.Scanner;
parser : HTMLParser.Parser;
transformer : HTMLTransformer.Transformer;
xmlDoc : XML.Document;
textWriter : TextUtilities.TextWriter;
bgImage : WebBrowserComponents.TileImagePanel;
decoder : Codecs.TextDecoder;
bbtDecoder : TextUtilities.BluebottleDecoder;
encoder : Codecs.TextEncoder;
res : LONGINT;
contents: XMLObjects.Enumerator;
content: ANY;
framesetElem : XML.Element;
frameset : FramesetPanel;
titleElem : XML.Element;
item : HTMLTransformer.EmbeddedObject;
PROCEDURE &New*(VAR title : String; rc :WebBrowserComponents.ResourceConnection; width : LONGINT; height : LONGINT; scrollbars : BOOLEAN; loadLink : WMEvents.EventListener; charset : String; frameName : String);
VAR
sharpPos : LONGINT;
wrp : WMTextView.LinkWrapper;
sequencer : Messages.MsgSequencer;
BEGIN
Init;
NEW(sequencer, Handle);
SetSequencer(sequencer);
takesFocus.Set(FALSE);
SELF.rc := rc;
SELF.width := width;
SELF.height := height;
SELF.scrollbars := scrollbars;
SELF.loadLink := loadLink;
SELF.charset := charset;
SELF.frameName := frameName;
alignment.Set(WMComponents.AlignClient);
firstResize := TRUE;
Load(title);
sharpPos := Strings.LastIndexOfByte2("#", rc.url^);
IF sharpPos # -1 THEN
NEW(wrp);
wrp.link := Strings.Substring2(sharpPos, rc.url^);
tv.LinkClicked(SELF, wrp);
END;
END New;
PROCEDURE Load(VAR title : String);
BEGIN
IF verbose THEN KernelLog.String("---Loading HTMLPanel. Url: "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
IF outputMode = modeSourceCode THEN
decoder := Codecs.GetTextDecoder("ISO8859-1");
decoder.Open(rc.reader, res);
NEW(text);
NEW(textWriter, text);
encoder := Codecs.GetTextEncoder("UTF-8");
encoder.Open(textWriter);
encoder.WriteText(decoder.GetText(), res);
textWriter.Update;
NEW(vScrollbar);
vScrollbar.alignment.Set(WMComponents.AlignRight);
AddContent(vScrollbar);
NEW(hScrollbar);
hScrollbar.alignment.Set(WMComponents.AlignBottom);
hScrollbar.vertical.Set(FALSE);
AddContent(hScrollbar);
NEW(tv);
tv.alignment.Set(WMComponents.AlignClient);
AddContent(tv);
tv.SetScrollbars(hScrollbar, vScrollbar);
tv.SetText(text);
tv.firstLine.Set(0);
ELSIF outputMode = modeParsedHtml THEN
NEW(scanner, rc.reader);
NEW(parser, scanner);
IF verbose THEN KernelLog.String("---Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
xmlDoc := parser.Parse();
IF verbose THEN KernelLog.String("---Parsing done."); KernelLog.Ln(); END;
NEW(text);
NEW(textWriter, text);
xmlDoc.Write(textWriter, NIL, 0);
textWriter.Update;
NEW(vScrollbar);
vScrollbar.alignment.Set(WMComponents.AlignRight);
AddContent(vScrollbar);
NEW(hScrollbar);
hScrollbar.alignment.Set(WMComponents.AlignBottom);
hScrollbar.vertical.Set(FALSE);
AddContent(hScrollbar);
NEW(tv);
tv.alignment.Set(WMComponents.AlignClient);
AddContent(tv);
tv.SetScrollbars(hScrollbar, vScrollbar);
tv.SetText(text);
tv.firstLine.Set(0);
ELSIF outputMode = modeBbtXml THEN
NEW(scanner, rc.reader);
NEW(parser, scanner);
IF verbose THEN KernelLog.String("---Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
xmlDoc := parser.Parse();
IF verbose THEN KernelLog.String("---Parsing done."); KernelLog.Ln(); END;
NEW(transformer, xmlDoc, rc.url, width, NIL, charset, NIL);
xmlDoc := transformer.Transform();
NEW(text);
NEW(textWriter, text);
xmlDoc.Write(textWriter, NIL, 0);
textWriter.Update;
NEW(vScrollbar);
vScrollbar.alignment.Set(WMComponents.AlignRight);
AddContent(vScrollbar);
NEW(hScrollbar);
hScrollbar.alignment.Set(WMComponents.AlignBottom);
hScrollbar.vertical.Set(FALSE);
AddContent(hScrollbar);
NEW(tv);
tv.alignment.Set(WMComponents.AlignClient);
AddContent(tv);
tv.SetScrollbars(hScrollbar, vScrollbar);
tv.SetText(text);
tv.firstLine.Set(0);
ELSE
NEW(scanner, rc.reader);
NEW(parser, scanner);
IF verbose THEN KernelLog.String("---Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
xmlDoc := parser.Parse();
IF verbose THEN KernelLog.String("---Parsing done."); KernelLog.Ln(); END;
contents := xmlDoc.GetContents();
WHILE contents.HasMoreElements() & (framesetElem = NIL) DO
content := contents.GetNext();
IF content IS XML.Element THEN
framesetElem := GetElement("FRAMESET", content(XML.Element));
END;
END;
IF framesetElem = NIL THEN
NEW(transformer, xmlDoc, rc.url, width, loadLink, charset, frameName);
xmlDoc := transformer.Transform();
title := transformer.title;
fillColor.Set(transformer.pageBgColor * 0100H + 0FFH);
IF transformer.bgImage # NIL THEN
NEW(bgImage, NIL, transformer.bgImage);
AddContent(bgImage);
END;
NEW(bbtDecoder);
bbtDecoder.OpenXML(xmlDoc);
text := bbtDecoder.GetText();
NEW(tv);
tv.alignment.Set(WMComponents.AlignClient);
tv.onLinkClicked.Add(loadLink);
IF scrollbars THEN
NEW(vScrollbar);
vScrollbar.alignment.Set(WMComponents.AlignRight);
AddContent(vScrollbar);
NEW(hScrollbar);
hScrollbar.alignment.Set(WMComponents.AlignBottom);
hScrollbar.vertical.Set(FALSE);
AddContent(hScrollbar);
tv.SetScrollbars(hScrollbar, vScrollbar);
END;
AddContent(tv);
tv.SetText(text);
tv.firstLine.Set(0);
ELSE
NEW(frameset, framesetElem, rc.url, width, height, loadLink);
AddContent(frameset);
contents := xmlDoc.GetContents();
WHILE contents.HasMoreElements() & (titleElem = NIL) DO
content := contents.GetNext();
IF content IS XML.Element THEN
titleElem := GetElement("TITLE", content(XML.Element));
END;
END;
IF titleElem # NIL THEN
title := NIL;
contents := titleElem.GetContents();
WHILE contents.HasMoreElements() & (title = NIL) DO
content := contents.GetNext();
IF content IS XML.ArrayChars THEN
title := content(XML.ArrayChars).GetStr();
Strings.TrimWS(title^);
title := HTMLTransformer.TransformCharEnt(title);
END;
END;
END;
END;
END;
rc.Release();
END Load;
PROCEDURE Resized*;
VAR
item : HTMLTransformer.EmbeddedObject;
width : LONGINT;
BEGIN
Resized^;
IF firstResize THEN firstResize := FALSE; RETURN END;
IF transformer # NIL THEN
width := bounds.GetWidth();
item := transformer.embeddedObjectsList;
WHILE item # NIL DO
IF item.object IS WebBrowserComponents.HR THEN
item.object(WebBrowserComponents.HR).ParentTvWidthChanged(width);
ELSIF item.object IS HTMLTransformer.Table THEN
item.object(HTMLTransformer.Table).ParentTvWidthChanged(width);
END;
item := item.prev;
END;
IF tv # NIL THEN
tv.SetText(text);
END;
END;
END Resized;
END HTMLPanel;
FramesetPanel = OBJECT (VisualComponent)
VAR
framesetElem : XML.Element;
baseAddress : String;
width : LONGINT;
height : LONGINT;
loadLink : WMEvents.EventListener;
frameborderSize : LONGINT;
totalFixSizes : LONGINT;
nodeIsCol : BOOLEAN;
firstFrame : FrameNode;
PROCEDURE &New*(framesetElem : XML.Element; baseAddress : String; width : LONGINT; height : LONGINT; loadLink : WMEvents.EventListener);
BEGIN
Init;
SELF.framesetElem := framesetElem;
SELF.baseAddress := baseAddress;
SELF.width := width;
SELF.height := height;
SELF.loadLink := loadLink;
takesFocus.Set(FALSE);
alignment.Set(WMComponents.AlignClient);
BuildFrameList();
AddFramesToPanel();
END New;
PROCEDURE BuildFrameList;
VAR
frameItem : FrameNode;
framesetItem : FramesetNode;
url, dummyTitle : String;
frameSlots : FrameslotNode;
framesets : FramesetNode;
slotItem : FrameslotNode;
framesetPanel : FramesetPanel;
fWidth, fHeight : LONGINT;
lastFrame : FrameNode;
BEGIN
ParseFramesetAttr(framesetElem, frameSlots, frameborderSize, totalFixSizes, nodeIsCol);
ParseFramesetContent(framesetElem, framesets);
framesetItem := framesets;
slotItem := frameSlots;
WHILE (slotItem # NIL) & (framesetItem # NIL) DO
NEW(frameItem);
frameItem.name := framesetItem.name;
frameItem.scrolling := framesetItem.scrolling;
frameItem.size := slotItem.size;
IF slotItem.type = typeFix THEN
frameItem.relative := FALSE;
ELSE
frameItem.relative := TRUE;
END;
fWidth := GetFrameWidth(frameItem);
fHeight := GetFrameHeight(frameItem);
IF framesetItem.frameset # NIL THEN
NEW(framesetPanel, framesetItem.frameset, baseAddress, fWidth, fHeight, LoadLink);
frameItem.panel := framesetPanel;
ELSE
IF (frameItem.name = NIL) OR (frameItem.name^ = "") THEN
frameItem.name := GetNewFrameName();
END;
url := HTMLTransformer.ResolveAddress(baseAddress, framesetItem.src);
frameItem.panel := GetContent(url, dummyTitle, fWidth, fHeight, frameItem.scrolling, LoadLink, frameItem.name);
END;
frameItem.isLast := FALSE;
IF lastFrame # NIL THEN
lastFrame.next := frameItem;
ELSE
firstFrame := frameItem;
END;
lastFrame := frameItem;
slotItem := slotItem.next;
framesetItem := framesetItem.next;
END;
IF lastFrame # NIL THEN
lastFrame.isLast := TRUE;
END;
frameItem := firstFrame;
WHILE frameItem # NIL DO
AlignFrame(frameItem);
frameItem := frameItem.next;
END;
END BuildFrameList;
PROCEDURE GetFrameWidth(frameItem : FrameNode) : LONGINT;
VAR
fWidth : LONGINT;
BEGIN
IF nodeIsCol THEN
IF frameItem.relative THEN
fWidth := ENTIER((width-totalFixSizes) / 100 * frameItem.size) - frameborderSize;
ELSE
fWidth := frameItem.size - frameborderSize;
END;
ELSE
fWidth := width;
END;
IF fWidth < 1 THEN fWidth := 1 END;
RETURN fWidth;
END GetFrameWidth;
PROCEDURE GetFrameHeight(frameItem : FrameNode) : LONGINT;
VAR
fHeight : LONGINT;
BEGIN
IF ~nodeIsCol THEN
IF frameItem.relative THEN
fHeight := ENTIER((height-totalFixSizes) / 100 * frameItem.size) - frameborderSize;
ELSE
fHeight := frameItem.size - frameborderSize;
END;
ELSE
fHeight := height;
END;
IF fHeight < 1 THEN fHeight := 1 END;
RETURN fHeight;
END GetFrameHeight;
PROCEDURE AlignFrame(frameItem : FrameNode);
VAR
resizer: WMStandardComponents.Resizer;
BEGIN
IF ~frameItem.isLast THEN
NEW(resizer);
frameItem.panel.AddContent(resizer);
IF nodeIsCol THEN
resizer.alignment.Set(WMComponents.AlignRight);
resizer.bounds.SetWidth(frameborderSize);
ELSE
resizer.alignment.Set(WMComponents.AlignBottom);
resizer.bounds.SetHeight(frameborderSize);
END;
IF nodeIsCol THEN
frameItem.panel.alignment.Set(WMComponents.AlignLeft);
ELSE
frameItem.panel.alignment.Set(WMComponents.AlignTop);
END;
ELSE
frameItem.panel.alignment.Set(WMComponents.AlignClient);
END;
END AlignFrame;
PROCEDURE Resize;
VAR
frameItem : FrameNode;
BEGIN
frameItem := firstFrame;
WHILE frameItem # NIL DO
IF nodeIsCol THEN
IF frameItem.relative THEN
frameItem.panel.bounds.SetWidth(ENTIER((width-totalFixSizes) / 100 * frameItem.size));
ELSE
frameItem.panel.bounds.SetWidth(frameItem.size);
END;
ELSE
IF frameItem.relative THEN
frameItem.panel.bounds.SetHeight(ENTIER((height-totalFixSizes) / 100 * frameItem.size));
ELSE
frameItem.panel.bounds.SetHeight(frameItem.size);
END;
END;
frameItem := frameItem.next;
END;
END Resize;
PROCEDURE Resized*;
BEGIN
width := bounds.GetWidth();
height := bounds.GetHeight();
Resize;
Resized^;
END Resized;
PROCEDURE RemoveFramesFromPanel;
VAR
frameItem : FrameNode;
BEGIN
frameItem := firstFrame;
WHILE frameItem # NIL DO
RemoveContent(frameItem.panel);
frameItem := frameItem.next;
END;
END RemoveFramesFromPanel;
PROCEDURE AddFramesToPanel;
VAR
frameItem : FrameNode;
BEGIN
frameItem := firstFrame;
WHILE frameItem # NIL DO
AddContent(frameItem.panel);
frameItem := frameItem.next;
END;
Resize();
END AddFramesToPanel;
PROCEDURE LoadLink(sender, data : ANY);
VAR
link, target, targetLow : String;
BEGIN
IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.LoadLink, sender, data)
ELSE
DecodeLinkData(data, link, target);
IF ~Strings.StartsWith2("#", link^) THEN
targetLow := Strings.LowerCaseInNew(target^);
IF (targetLow^ = "_parent") OR (targetLow^ = "_top") OR (targetLow^ = "_blank") THEN
loadLink(NIL, data);
ELSIF ~FindAndReloadFrame(link, target) THEN
loadLink(NIL, data);
END;
END;
END;
END LoadLink;
PROCEDURE FindAndReloadFrame(link, target : String) : BOOLEAN;
VAR
frameItem : FrameNode;
framesetPanel : FramesetPanel;
targetLow : String;
url, dummyTitle : String;
fWidth, fHeight : LONGINT;
BEGIN
frameItem := firstFrame;
WHILE frameItem # NIL DO
IF frameItem.name = NIL THEN
framesetPanel := frameItem.panel(FramesetPanel);
IF framesetPanel.FindAndReloadFrame(link, target) THEN
RETURN TRUE;
END;
ELSE
targetLow := Strings.LowerCaseInNew(target^);
IF (target^ = frameItem.name^) OR (targetLow^ = "_self") THEN
RemoveFramesFromPanel();
fWidth := GetFrameWidth(frameItem);
fHeight := GetFrameHeight(frameItem);
url := HTMLTransformer.ResolveAddress(baseAddress, link);
frameItem.panel := GetContent(url, dummyTitle, fWidth, fHeight, frameItem.scrolling, LoadLink, frameItem.name);
AlignFrame(frameItem);
AddFramesToPanel;
Reset(SELF, NIL);
AlignSubComponents();
Invalidate();
RETURN TRUE;
END;
END;
frameItem := frameItem.next;
END;
RETURN FALSE;
END FindAndReloadFrame;
END FramesetPanel;
VAR
frameNameCount : LONGINT;
PROCEDURE GetContent(VAR url : String; VAR title : String; initWidth : LONGINT; initHeight : LONGINT; scrollbars : BOOLEAN; loadLink : WMEvents.EventListener; frameName : String) : VisualComponent;
VAR
rc : WebBrowserComponents.ResourceConnection;
panel : VisualComponent;
errorText : WebBrowserComponents.ShortText;
image : WebBrowserComponents.StretchImagePanel;
htmlPanel : HTMLPanel;
textPanel : WebBrowserComponents.TextPanel;
s : String;
charset : String;
charsetPos : LONGINT;
BEGIN
rc := WebBrowserComponents.GetResourceConnection(url);
IF rc = NIL THEN
IF verbose THEN KernelLog.String("Not found: "); KernelLog.String(url^); KernelLog.Ln; END;
s := Strings.ConcatToNew(" Not found: ", url^);
NEW(errorText, s^);
panel := errorText;
ELSE
url := rc.url;
IF Strings.StartsWith2("text/html", rc.mimeType^) OR (rc.mimeType^ = "") THEN
s := Strings.LowerCaseInNew(rc.mimeType^);
IF Strings.Pos("charset", s^) >= 0 THEN
charsetPos := Strings.IndexOfByte('=', charsetPos, rc.mimeType^) + 1;
IF (charsetPos >= 0) & (charsetPos < Strings.Length(rc.mimeType^)) THEN
charset := Strings.Substring2(charsetPos, rc.mimeType^);
Strings.TrimWS(charset^);
END;
END;
NEW(htmlPanel, title, rc, initWidth, initHeight, scrollbars, loadLink, charset, frameName);
panel := htmlPanel;
ELSIF Strings.StartsWith2("text/plain", rc.mimeType^) OR Strings.StartsWith2("application/xml", rc.mimeType^) THEN
NEW(textPanel, rc, NIL);
panel := textPanel;
ELSIF Strings.StartsWith2("image/", rc.mimeType^) THEN
NEW(image, rc, NIL, -1, -1);
panel := image;
ELSE
IF verbose THEN KernelLog.String("Unknown content type: "); KernelLog.String(rc.mimeType^); KernelLog.Ln; END;
s := Strings.ConcatToNew(" Unknown content type: ", rc.mimeType^);
NEW(errorText, s^);
panel := errorText;
rc.Stop();
rc.Release();
END;
END;
RETURN panel;
END GetContent;
PROCEDURE DecodeLinkData*(data : ANY; VAR link : String; VAR target : String);
VAR
linkValue : String;
urlPos, len : LONGINT;
BEGIN
linkValue := data(WMTextView.LinkWrapper).link;
IF Strings.StartsWith2("#", linkValue^) THEN
link := linkValue;
target := Strings.NewString("_self");
ELSE
urlPos := Strings.Pos(";url=", linkValue^);
target := Strings.Substring(7, urlPos, linkValue^);
len := Strings.Length(linkValue^);
IF len > (urlPos + 5) THEN
link := Strings.Substring(urlPos + 5, len, linkValue^);
ELSE
link := Strings.NewString("");
END;
END;
END DecodeLinkData;
PROCEDURE GetElement(name : ARRAY OF CHAR; root : XML.Element) : XML.Element;
VAR
rootName : String;
contents: XMLObjects.Enumerator;
content: ANY;
retElement: XML.Element;
BEGIN
IF root = NIL THEN RETURN NIL; END;
rootName := root.GetName();
IF rootName^ = name THEN RETURN root; END;
contents := root.GetContents();
WHILE contents.HasMoreElements() & (retElement = NIL) DO
content := contents.GetNext();
IF content IS XML.Element THEN
retElement := GetElement(name, content(XML.Element));
END;
END;
RETURN retElement;
END GetElement;
PROCEDURE ParseFramesetAttr(frameset : XML.Element; VAR frameSlots : FrameslotNode; VAR frameborderSize : LONGINT; VAR fixSizes : LONGINT; VAR nodeIsCol : BOOLEAN);
VAR
s : String;
rowsNode : FrameslotNode;
colsNode : FrameslotNode;
rowsCount : LONGINT;
colsCount : LONGINT;
rowsfixSizes : LONGINT;
colsfixSizes : LONGINT;
BEGIN
rowsCount := 0;
colsCount := 0;
s := HTMLTransformer.GetElemAttributeValue(frameset, "rows", FALSE);
IF s # NIL THEN
ParseFramesetRowsOrCols(s, rowsNode, rowsCount, rowsfixSizes);
END;
s := HTMLTransformer.GetElemAttributeValue(frameset, "cols", FALSE);
IF s # NIL THEN
ParseFramesetRowsOrCols(s, colsNode, colsCount, colsfixSizes);
END;
IF (rowsCount = 0) & (colsCount = 0) THEN
NEW(frameSlots);
fixSizes := 0;
nodeIsCol := FALSE;
frameSlots.size := 100;
frameSlots.type := typePercent;
ELSIF rowsCount >= colsCount THEN
frameSlots := rowsNode;
fixSizes := rowsfixSizes;
nodeIsCol := FALSE;
ELSE
frameSlots := colsNode;
fixSizes := colsfixSizes;
nodeIsCol := TRUE;
END;
frameborderSize := 6;
s := HTMLTransformer.GetElemAttributeValue(frameset, "frameborder", FALSE);
IF s # NIL THEN
Strings.TrimWS(s^);
Strings.StrToInt(s^, frameborderSize);
ELSE
s := HTMLTransformer.GetElemAttributeValue(frameset, "border", FALSE);
IF s # NIL THEN
Strings.TrimWS(s^);
Strings.StrToInt(s^, frameborderSize);
END;
END;
END ParseFramesetAttr;
PROCEDURE ParseFramesetRowsOrCols(attrValue : String; VAR firstSlot : FrameslotNode; VAR nodeCount : LONGINT; VAR fixSizes : LONGINT);
VAR
start : LONGINT;
comma : LONGINT;
s : String;
sizeStr : String;
size : LONGINT;
type : LONGINT;
slotItem : FrameslotNode;
lastSlot : FrameslotNode;
prevSlot : FrameslotNode;
percents : LONGINT;
parts : LONGINT;
factor : REAL;
onePart : LONGINT;
BEGIN
percents := 0;
parts := 0;
fixSizes := 0;
firstSlot := NIL;
start := 0;
REPEAT
comma := Strings.IndexOfByte(',', start, attrValue^);
IF comma = -1 THEN
s := Strings.Substring2(start, attrValue^);
ELSE
s := Strings.Substring(start, comma, attrValue^);
start := comma+1;
END;
Strings.TrimWS(s^);
IF Strings.EndsWith("%", s^) THEN
sizeStr := Strings.Substring(0, Strings.Length(s^)-1, s^);
Strings.StrToInt(sizeStr^, size);
type := typePercent;
ELSIF Strings.EndsWith("*", s^) THEN
IF Strings.Length(s^) = 1 THEN
size := 1;
ELSE
sizeStr := Strings.Substring(0, Strings.Length(s^)-1, s^);
Strings.TrimWS(sizeStr^);
Strings.StrToInt(sizeStr^, size);
END;
type := typeParts;
ELSE
Strings.StrToInt(s^, size);
type := typeFix;
END;
IF size > 0 THEN
NEW(slotItem);
slotItem.size := size;
slotItem.type := type;
IF type = typePercent THEN
percents := percents + size;
ELSIF type = typeParts THEN
parts := parts + size;
ELSE
fixSizes := fixSizes + size;
END;
IF lastSlot # NIL THEN
lastSlot.next := slotItem;
lastSlot := slotItem;
ELSE
firstSlot := slotItem;
lastSlot := slotItem;
END;
END;
UNTIL comma = -1;
IF (percents > 100) OR (parts = 0) THEN
IF percents > 0 THEN
factor := 100 / percents;
END;
onePart := 0;
ELSE
factor := 1;
onePart := ENTIER((100 - percents) / parts);
END;
nodeCount := 0;
slotItem := firstSlot;
prevSlot := NIL;
WHILE slotItem # NIL DO
IF slotItem.type = typePercent THEN
slotItem.size := ENTIER(slotItem.size * factor);
ELSIF slotItem.type = typeParts THEN
slotItem.size := slotItem.size * onePart;
END;
IF slotItem.size = 0 THEN
IF prevSlot # NIL THEN
prevSlot.next := slotItem.next;
ELSE
firstSlot := slotItem.next;
END;
ELSE
INC(nodeCount);
prevSlot := slotItem;
END;
slotItem := slotItem.next;
END;
END ParseFramesetRowsOrCols;
PROCEDURE ParseFramesetContent(frameset : XML.Element; VAR first : FramesetNode);
VAR
last : FramesetNode;
node : FramesetNode;
enum : XMLObjects.Enumerator;
p : ANY;
frame : XML.Element;
name : String;
s : String;
BEGIN
first := NIL;
last := NIL;
enum := frameset.GetContents();
WHILE enum.HasMoreElements() DO
p := enum.GetNext();
IF p IS XML.Element THEN
frame := p(XML.Element);
name := frame.GetName();
IF name^ = "FRAMESET" THEN
NEW(node);
node.frameset := frame;
IF last # NIL THEN
last.next := node;
last := node;
ELSE
first := node;
last := node;
END;
ELSIF name^ = "FRAME" THEN
s := HTMLTransformer.GetElemAttributeValue(frame, "src", FALSE);
IF s # NIL THEN
Strings.TrimWS(s^);
IF s^ # "" THEN
NEW(node);
node.src := s;
s := HTMLTransformer.GetElemAttributeValue(frame, "name", FALSE);
IF s # NIL THEN
Strings.TrimWS(s^);
node.name := s;
END;
node.scrolling := TRUE;
s := HTMLTransformer.GetElemAttributeValue(frame, "scrolling", TRUE);
IF s # NIL THEN
Strings.TrimWS(s^);
IF s^ = "no" THEN
node.scrolling := FALSE;
END;
END;
IF last # NIL THEN
last.next := node;
last := node;
ELSE
first := node;
last := node;
END;
END;
END;
END;
END;
END;
END ParseFramesetContent;
PROCEDURE GetNewFrameName() : String;
VAR
id : ARRAY 28 OF CHAR;
nr : ARRAY 8 OF CHAR;
BEGIN {EXCLUSIVE}
id := "BimBrowser-Frame-ID-";
Strings.IntToStr(frameNameCount, nr);
Strings.Append(id, nr);
INC(frameNameCount);
RETURN Strings.NewString(id);
END GetNewFrameName;
BEGIN
frameNameCount := 0;
END WebBrowserPanel.