WebBrowserPanel.Mod 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. MODULE WebBrowserPanel; (** AUTHOR "Simon L. Keel"; PURPOSE "components for loading and displaying web-pages"; *)
  2. IMPORT
  3. HTMLScanner, HTMLParser, HTMLTransformer, WebBrowserComponents,
  4. WMComponents, WMProperties, WMTextView, WMStandardComponents, Texts, WMEvents, TextUtilities,
  5. Codecs, XML, XMLObjects, Strings, KernelLog, Messages := WMMessages;
  6. CONST
  7. verbose = TRUE;
  8. modeSourceCode = 0;
  9. modeParsedHtml = 1;
  10. modeBbtXml = 2;
  11. modeBbtText = 3;
  12. outputMode = modeBbtText;
  13. typePercent = 0;
  14. typeParts = 1;
  15. typeFix = 2;
  16. TYPE
  17. String = Strings.String;
  18. VisualComponent = WMComponents.VisualComponent;
  19. NotifyMsg* = POINTER TO RECORD
  20. url* : String;
  21. title* : String;
  22. loadID* : LONGINT;
  23. END;
  24. LoadedMsg* = POINTER TO RECORD
  25. vc : VisualComponent;
  26. url : String;
  27. title : String;
  28. END;
  29. FrameNode = POINTER TO RECORD
  30. next : FrameNode;
  31. name : String;
  32. scrolling : BOOLEAN;
  33. size : LONGINT;
  34. relative : BOOLEAN;
  35. panel : VisualComponent;
  36. isLast : BOOLEAN;
  37. END;
  38. FrameslotNode = POINTER TO RECORD
  39. next : FrameslotNode;
  40. size : LONGINT;
  41. type : LONGINT;
  42. END;
  43. FramesetNode = POINTER TO RECORD
  44. next : FramesetNode;
  45. frameset : XML.Element;
  46. src : String;
  47. name : String;
  48. scrolling : BOOLEAN;
  49. END;
  50. WebPanel* = OBJECT (VisualComponent)
  51. VAR
  52. url- : WMProperties.StringProperty;
  53. notify* : WMEvents.EventListener;
  54. openNewWindow* : PROCEDURE {DELEGATE} (url : String);
  55. loadLink* : WMEvents.EventListener;
  56. vc : VisualComponent;
  57. loadingText : WebBrowserComponents.ShortText;
  58. pending : BOOLEAN;
  59. loadID : LONGINT;
  60. PROCEDURE &Init*;
  61. VAR
  62. s : String;
  63. BEGIN
  64. Init^;
  65. takesFocus.Set(FALSE);
  66. NEW(url, NIL, Strings.NewString("WebPanel URL"), Strings.NewString("Stores the URL of a WebPanel"));
  67. s := Strings.NewString(" Loading...");
  68. NEW(loadingText, s^);
  69. pending := FALSE;
  70. END Init;
  71. PROCEDURE Load*(loadID : LONGINT);
  72. VAR
  73. cl : ContentLoader;
  74. BEGIN (*{EXCLUSIVE} ??*)
  75. IF ~pending THEN
  76. pending := TRUE;
  77. SELF.loadID := loadID;
  78. IF vc # NIL THEN
  79. RemoveContent(vc);
  80. END;
  81. AddContent(loadingText);
  82. Reset(SELF, NIL);
  83. AlignSubComponents();
  84. Invalidate();
  85. NEW(cl, SELF);
  86. END;
  87. END Load;
  88. PROCEDURE Loaded(sender, data : ANY);
  89. VAR
  90. msg : LoadedMsg;
  91. notifyMsg : NotifyMsg;
  92. BEGIN
  93. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Loaded, sender, data)
  94. ELSE
  95. RemoveContent(loadingText);
  96. msg := data(LoadedMsg);
  97. vc := msg.vc;
  98. AddContent(vc);
  99. NEW(notifyMsg);
  100. notifyMsg.url := msg.url;
  101. notifyMsg.title := msg.title;
  102. notifyMsg.loadID := loadID;
  103. notify(SELF, notifyMsg);
  104. Reset(SELF, NIL);
  105. AlignSubComponents();
  106. Invalidate();
  107. pending := FALSE;
  108. END;
  109. END Loaded;
  110. PROCEDURE LoadLink(sender, data : ANY);
  111. VAR
  112. link, target : String;
  113. targetLow : String;
  114. BEGIN
  115. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.LoadLink, sender, data)
  116. ELSE
  117. DecodeLinkData(data, link, target);
  118. IF Strings.StartsWith2("#", link^) THEN
  119. (* TODO: notify WebBrowser.Window about new URL !! *)
  120. ELSE
  121. targetLow := Strings.LowerCaseInNew(target^);
  122. IF (target^ = "") OR (targetLow^ = "_self") OR (targetLow^ = "_top") OR (targetLow^ = "_parent") THEN
  123. IF loadLink # NIL THEN
  124. loadLink(SELF, data);
  125. ELSE
  126. url.Set(link);
  127. Load(-1);
  128. END;
  129. ELSE
  130. IF openNewWindow # NIL THEN
  131. openNewWindow(link);
  132. END;
  133. END;
  134. END;
  135. END;
  136. END LoadLink;
  137. END WebPanel;
  138. ContentLoader = OBJECT
  139. VAR
  140. webPanel : WebPanel;
  141. msg : LoadedMsg;
  142. vc : VisualComponent;
  143. url : String;
  144. title : String;
  145. encodedUrl: ARRAY 1024 OF CHAR;
  146. PROCEDURE &New*(webPanel : WebPanel);
  147. BEGIN
  148. SELF.webPanel := webPanel;
  149. END New;
  150. BEGIN {ACTIVE}
  151. NEW(msg);
  152. msg.url := webPanel.url.Get();
  153. IF verbose THEN KernelLog.String("ContentLoader: Loading: "); KernelLog.String(msg.url^); KernelLog.Ln; END;
  154. msg.vc := GetContent(msg.url, msg.title, webPanel.bounds.GetWidth(), webPanel.bounds.GetHeight(), TRUE, webPanel.LoadLink, NIL);
  155. webPanel.Loaded(SELF, msg);
  156. IF verbose THEN KernelLog.String("ContentLoader: Loading done."); KernelLog.Ln; END;
  157. END ContentLoader;
  158. HTMLPanel = OBJECT (VisualComponent)
  159. VAR
  160. rc : WebBrowserComponents.ResourceConnection;
  161. width : LONGINT;
  162. height : LONGINT;
  163. scrollbars : BOOLEAN;
  164. loadLink : WMEvents.EventListener;
  165. charset : String;
  166. frameName : String;
  167. firstResize : BOOLEAN;
  168. tv : WMTextView.TextView;
  169. text : Texts.Text;
  170. blankText : Texts.Text;
  171. vScrollbar : WMStandardComponents.Scrollbar;
  172. hScrollbar : WMStandardComponents.Scrollbar;
  173. scanner : HTMLScanner.Scanner;
  174. parser : HTMLParser.Parser;
  175. transformer : HTMLTransformer.Transformer;
  176. xmlDoc : XML.Document;
  177. textWriter : TextUtilities.TextWriter;
  178. bgImage : WebBrowserComponents.TileImagePanel;
  179. decoder : Codecs.TextDecoder;
  180. bbtDecoder : TextUtilities.BluebottleDecoder;
  181. encoder : Codecs.TextEncoder;
  182. res : WORD;
  183. contents: XMLObjects.Enumerator;
  184. content: ANY;
  185. framesetElem : XML.Element;
  186. frameset : FramesetPanel;
  187. titleElem : XML.Element;
  188. item : HTMLTransformer.EmbeddedObject;
  189. PROCEDURE &New*(VAR title : String; rc :WebBrowserComponents.ResourceConnection; width : LONGINT; height : LONGINT; scrollbars : BOOLEAN; loadLink : WMEvents.EventListener; charset : String; frameName : String);
  190. VAR
  191. sharpPos : SIZE;
  192. wrp : WMTextView.LinkWrapper;
  193. sequencer : Messages.MsgSequencer;
  194. BEGIN
  195. Init;
  196. NEW(sequencer, Handle);
  197. SetSequencer(sequencer);
  198. takesFocus.Set(FALSE);
  199. SELF.rc := rc;
  200. SELF.width := width;
  201. SELF.height := height;
  202. SELF.scrollbars := scrollbars;
  203. SELF.loadLink := loadLink;
  204. SELF.charset := charset;
  205. SELF.frameName := frameName;
  206. alignment.Set(WMComponents.AlignClient);
  207. firstResize := TRUE;
  208. Load(title);
  209. (* doesn't work... *)
  210. sharpPos := Strings.LastIndexOfByte2("#", rc.url^);
  211. IF sharpPos # -1 THEN
  212. NEW(wrp);
  213. wrp.link := Strings.Substring2(sharpPos, rc.url^);
  214. tv.LinkClicked(SELF, wrp);
  215. END;
  216. END New;
  217. PROCEDURE Load(VAR title : String);
  218. BEGIN
  219. IF verbose THEN KernelLog.String("---Loading HTMLPanel. Url: "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
  220. IF outputMode = modeSourceCode THEN
  221. decoder := Codecs.GetTextDecoder("ISO8859-1");
  222. decoder.Open(rc.reader, res);
  223. NEW(text);
  224. NEW(textWriter, text);
  225. encoder := Codecs.GetTextEncoder("UTF-8");
  226. encoder.Open(textWriter);
  227. encoder.WriteText(decoder.GetText(), res);
  228. textWriter.Update;
  229. (* Show *)
  230. NEW(vScrollbar);
  231. vScrollbar.alignment.Set(WMComponents.AlignRight);
  232. AddContent(vScrollbar);
  233. NEW(hScrollbar);
  234. hScrollbar.alignment.Set(WMComponents.AlignBottom);
  235. hScrollbar.vertical.Set(FALSE);
  236. AddContent(hScrollbar);
  237. NEW(tv);
  238. tv.alignment.Set(WMComponents.AlignClient);
  239. AddContent(tv);
  240. tv.SetScrollbars(hScrollbar, vScrollbar);
  241. tv.SetText(text);
  242. tv.firstLine.Set(0);
  243. ELSIF outputMode = modeParsedHtml THEN
  244. (* Parse the page *)
  245. NEW(scanner, rc.reader);
  246. NEW(parser, scanner);
  247. IF verbose THEN KernelLog.String("-Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
  248. xmlDoc := parser.Parse();
  249. IF verbose THEN KernelLog.String("-Parsing done."); KernelLog.Ln(); END;
  250. NEW(text);
  251. NEW(textWriter, text);
  252. xmlDoc.Write(textWriter, NIL, 0);
  253. textWriter.Update;
  254. (* Show *)
  255. NEW(vScrollbar);
  256. vScrollbar.alignment.Set(WMComponents.AlignRight);
  257. AddContent(vScrollbar);
  258. NEW(hScrollbar);
  259. hScrollbar.alignment.Set(WMComponents.AlignBottom);
  260. hScrollbar.vertical.Set(FALSE);
  261. AddContent(hScrollbar);
  262. NEW(tv);
  263. tv.alignment.Set(WMComponents.AlignClient);
  264. AddContent(tv);
  265. tv.SetScrollbars(hScrollbar, vScrollbar);
  266. tv.SetText(text);
  267. tv.firstLine.Set(0);
  268. ELSIF outputMode = modeBbtXml THEN
  269. (* Parse the page *)
  270. NEW(scanner, rc.reader);
  271. NEW(parser, scanner);
  272. IF verbose THEN KernelLog.String("--Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
  273. xmlDoc := parser.Parse();
  274. IF verbose THEN KernelLog.String("--Parsing done."); KernelLog.Ln(); END;
  275. (* Transform the document *)
  276. NEW(transformer, xmlDoc, rc.url, width, NIL, charset, NIL);
  277. xmlDoc := transformer.Transform();
  278. NEW(text);
  279. NEW(textWriter, text);
  280. xmlDoc.Write(textWriter, NIL, 0);
  281. textWriter.Update;
  282. (* Show *)
  283. NEW(vScrollbar);
  284. vScrollbar.alignment.Set(WMComponents.AlignRight);
  285. AddContent(vScrollbar);
  286. NEW(hScrollbar);
  287. hScrollbar.alignment.Set(WMComponents.AlignBottom);
  288. hScrollbar.vertical.Set(FALSE);
  289. AddContent(hScrollbar);
  290. NEW(tv);
  291. tv.alignment.Set(WMComponents.AlignClient);
  292. AddContent(tv);
  293. tv.SetScrollbars(hScrollbar, vScrollbar);
  294. tv.SetText(text);
  295. tv.firstLine.Set(0);
  296. ELSE (* outputMode = modeBbtText *)
  297. (* Parse the page *)
  298. NEW(scanner, rc.reader);
  299. NEW(parser, scanner);
  300. IF verbose THEN KernelLog.String("---Parsing "); KernelLog.String(rc.url^); KernelLog.Ln(); END;
  301. xmlDoc := parser.Parse();
  302. IF verbose THEN KernelLog.String("---Parsing done."); KernelLog.Ln(); END;
  303. (* Check for FRAMESET *)
  304. contents := xmlDoc.GetContents();
  305. WHILE contents.HasMoreElements() & (framesetElem = NIL) DO
  306. content := contents.GetNext();
  307. IF content IS XML.Element THEN
  308. framesetElem := GetElement("FRAMESET", content(XML.Element));
  309. END;
  310. END;
  311. IF framesetElem = NIL THEN
  312. (* Transform the document *)
  313. NEW(transformer, xmlDoc, rc.url, width, loadLink, charset, frameName);
  314. xmlDoc := transformer.Transform();
  315. title := transformer.title;
  316. fillColor.Set(transformer.pageBgColor * 0100H + 0FFH);
  317. IF transformer.bgImage # NIL THEN
  318. NEW(bgImage, NIL, transformer.bgImage);
  319. AddContent(bgImage);
  320. END;
  321. NEW(bbtDecoder);
  322. bbtDecoder.OpenXML(xmlDoc);
  323. text := bbtDecoder.GetText();
  324. (* Show *)
  325. NEW(tv);
  326. tv.alignment.Set(WMComponents.AlignClient);
  327. tv.onLinkClicked.Add(loadLink);
  328. IF scrollbars THEN
  329. NEW(vScrollbar);
  330. vScrollbar.alignment.Set(WMComponents.AlignRight);
  331. AddContent(vScrollbar);
  332. NEW(hScrollbar);
  333. hScrollbar.alignment.Set(WMComponents.AlignBottom);
  334. hScrollbar.vertical.Set(FALSE);
  335. AddContent(hScrollbar);
  336. tv.SetScrollbars(hScrollbar, vScrollbar);
  337. END;
  338. AddContent(tv);
  339. tv.SetText(text);
  340. tv.firstLine.Set(0);
  341. ELSE
  342. NEW(frameset, framesetElem, rc.url, width, height, loadLink);
  343. AddContent(frameset);
  344. contents := xmlDoc.GetContents();
  345. WHILE contents.HasMoreElements() & (titleElem = NIL) DO
  346. content := contents.GetNext();
  347. IF content IS XML.Element THEN
  348. titleElem := GetElement("TITLE", content(XML.Element));
  349. END;
  350. END;
  351. IF titleElem # NIL THEN
  352. title := NIL;
  353. contents := titleElem.GetContents();
  354. WHILE contents.HasMoreElements() & (title = NIL) DO
  355. content := contents.GetNext();
  356. IF content IS XML.ArrayChars THEN
  357. title := content(XML.ArrayChars).GetStr();
  358. Strings.TrimWS(title^);
  359. title := HTMLTransformer.TransformCharEnt(title);
  360. END;
  361. END;
  362. END;
  363. END;
  364. END;
  365. rc.Release();
  366. END Load;
  367. PROCEDURE Resized*;
  368. VAR
  369. item : HTMLTransformer.EmbeddedObject;
  370. width : LONGINT;
  371. BEGIN
  372. Resized^;
  373. (* ignore first resize, because webPanel is not drawn for the first time yet! *)
  374. IF firstResize THEN firstResize := FALSE; RETURN END;
  375. IF transformer # NIL THEN
  376. width := bounds.GetWidth();
  377. item := transformer.embeddedObjectsList;
  378. WHILE item # NIL DO
  379. IF item.object IS WebBrowserComponents.HR THEN
  380. item.object(WebBrowserComponents.HR).ParentTvWidthChanged(width);
  381. ELSIF item.object IS HTMLTransformer.Table THEN
  382. item.object(HTMLTransformer.Table).ParentTvWidthChanged(width);
  383. END;
  384. item := item.prev;
  385. END;
  386. IF tv # NIL THEN
  387. (* Resets the TextView, such that all embedded objects are new aligned! *)
  388. tv.SetText(text);
  389. END;
  390. END;
  391. END Resized;
  392. END HTMLPanel;
  393. FramesetPanel = OBJECT (VisualComponent)
  394. VAR
  395. framesetElem : XML.Element;
  396. baseAddress : String;
  397. width : LONGINT;
  398. height : LONGINT;
  399. loadLink : WMEvents.EventListener;
  400. frameborderSize : LONGINT;
  401. totalFixSizes : LONGINT;
  402. nodeIsCol : BOOLEAN;
  403. firstFrame : FrameNode;
  404. PROCEDURE &New*(framesetElem : XML.Element; baseAddress : String; width : LONGINT; height : LONGINT; loadLink : WMEvents.EventListener);
  405. BEGIN
  406. Init;
  407. SELF.framesetElem := framesetElem;
  408. SELF.baseAddress := baseAddress;
  409. SELF.width := width;
  410. SELF.height := height;
  411. SELF.loadLink := loadLink;
  412. takesFocus.Set(FALSE);
  413. alignment.Set(WMComponents.AlignClient);
  414. BuildFrameList();
  415. AddFramesToPanel();
  416. END New;
  417. PROCEDURE BuildFrameList;
  418. VAR
  419. frameItem : FrameNode;
  420. framesetItem : FramesetNode;
  421. url, dummyTitle : String;
  422. frameSlots : FrameslotNode;
  423. framesets : FramesetNode;
  424. slotItem : FrameslotNode;
  425. framesetPanel : FramesetPanel;
  426. fWidth, fHeight : LONGINT;
  427. lastFrame : FrameNode;
  428. BEGIN
  429. ParseFramesetAttr(framesetElem, frameSlots, frameborderSize, totalFixSizes, nodeIsCol);
  430. ParseFramesetContent(framesetElem, framesets);
  431. (* add frames and framesets to frame-list *)
  432. framesetItem := framesets;
  433. slotItem := frameSlots;
  434. WHILE (slotItem # NIL) & (framesetItem # NIL) DO
  435. NEW(frameItem);
  436. frameItem.name := framesetItem.name;
  437. frameItem.scrolling := framesetItem.scrolling;
  438. frameItem.size := slotItem.size;
  439. IF slotItem.type = typeFix THEN
  440. frameItem.relative := FALSE;
  441. ELSE
  442. frameItem.relative := TRUE;
  443. END;
  444. fWidth := GetFrameWidth(frameItem);
  445. fHeight := GetFrameHeight(frameItem);
  446. (* new frame or frameset *)
  447. IF framesetItem.frameset # NIL THEN
  448. NEW(framesetPanel, framesetItem.frameset, baseAddress, fWidth, fHeight, LoadLink);
  449. frameItem.panel := framesetPanel;
  450. ELSE
  451. IF (frameItem.name = NIL) OR (frameItem.name^ = "") THEN
  452. frameItem.name := GetNewFrameName();
  453. END;
  454. url := HTMLTransformer.ResolveAddress(baseAddress, framesetItem.src);
  455. frameItem.panel := GetContent(url, dummyTitle, fWidth, fHeight, frameItem.scrolling, LoadLink, frameItem.name);
  456. END;
  457. frameItem.isLast := FALSE;
  458. IF lastFrame # NIL THEN
  459. lastFrame.next := frameItem;
  460. ELSE
  461. firstFrame := frameItem;
  462. END;
  463. lastFrame := frameItem;
  464. slotItem := slotItem.next;
  465. framesetItem := framesetItem.next;
  466. END;
  467. IF lastFrame # NIL THEN
  468. lastFrame.isLast := TRUE;
  469. END;
  470. (* set frame alignment *)
  471. frameItem := firstFrame;
  472. WHILE frameItem # NIL DO
  473. AlignFrame(frameItem);
  474. frameItem := frameItem.next;
  475. END;
  476. END BuildFrameList;
  477. PROCEDURE GetFrameWidth(frameItem : FrameNode) : LONGINT;
  478. VAR
  479. fWidth : LONGINT;
  480. BEGIN
  481. (* calculate frame-width *)
  482. IF nodeIsCol THEN
  483. IF frameItem.relative THEN
  484. fWidth := ENTIER((width-totalFixSizes) / 100 * frameItem.size) - frameborderSize;
  485. ELSE
  486. fWidth := frameItem.size - frameborderSize;
  487. END;
  488. ELSE
  489. fWidth := width;
  490. END;
  491. IF fWidth < 1 THEN fWidth := 1 END;
  492. RETURN fWidth;
  493. END GetFrameWidth;
  494. PROCEDURE GetFrameHeight(frameItem : FrameNode) : LONGINT;
  495. VAR
  496. fHeight : LONGINT;
  497. BEGIN
  498. (* calculate frame-height *)
  499. IF ~nodeIsCol THEN
  500. IF frameItem.relative THEN
  501. fHeight := ENTIER((height-totalFixSizes) / 100 * frameItem.size) - frameborderSize;
  502. ELSE
  503. fHeight := frameItem.size - frameborderSize;
  504. END;
  505. ELSE
  506. fHeight := height;
  507. END;
  508. IF fHeight < 1 THEN fHeight := 1 END;
  509. RETURN fHeight;
  510. END GetFrameHeight;
  511. PROCEDURE AlignFrame(frameItem : FrameNode);
  512. VAR
  513. resizer: WMStandardComponents.Resizer;
  514. BEGIN
  515. IF ~frameItem.isLast THEN
  516. (* add resizer and set its width *)
  517. NEW(resizer);
  518. frameItem.panel.AddContent(resizer);
  519. IF nodeIsCol THEN
  520. resizer.alignment.Set(WMComponents.AlignRight);
  521. resizer.bounds.SetWidth(frameborderSize);
  522. ELSE
  523. resizer.alignment.Set(WMComponents.AlignBottom);
  524. resizer.bounds.SetHeight(frameborderSize);
  525. END;
  526. (* set frame alignment *)
  527. IF nodeIsCol THEN
  528. frameItem.panel.alignment.Set(WMComponents.AlignLeft);
  529. ELSE
  530. frameItem.panel.alignment.Set(WMComponents.AlignTop);
  531. END;
  532. ELSE
  533. (* set frame alignment for last frame*)
  534. frameItem.panel.alignment.Set(WMComponents.AlignClient);
  535. END;
  536. END AlignFrame;
  537. PROCEDURE Resize;
  538. VAR
  539. frameItem : FrameNode;
  540. BEGIN
  541. frameItem := firstFrame;
  542. WHILE frameItem # NIL DO
  543. IF nodeIsCol THEN
  544. IF frameItem.relative THEN
  545. frameItem.panel.bounds.SetWidth(ENTIER((width-totalFixSizes) / 100 * frameItem.size));
  546. ELSE
  547. frameItem.panel.bounds.SetWidth(frameItem.size);
  548. END;
  549. ELSE
  550. IF frameItem.relative THEN
  551. frameItem.panel.bounds.SetHeight(ENTIER((height-totalFixSizes) / 100 * frameItem.size));
  552. ELSE
  553. frameItem.panel.bounds.SetHeight(frameItem.size);
  554. END;
  555. END;
  556. frameItem := frameItem.next;
  557. END;
  558. END Resize;
  559. PROCEDURE Resized*;
  560. BEGIN
  561. width := bounds.GetWidth();
  562. height := bounds.GetHeight();
  563. Resize;
  564. Resized^;
  565. END Resized;
  566. PROCEDURE RemoveFramesFromPanel;
  567. VAR
  568. frameItem : FrameNode;
  569. BEGIN
  570. frameItem := firstFrame;
  571. WHILE frameItem # NIL DO
  572. RemoveContent(frameItem.panel);
  573. frameItem := frameItem.next;
  574. END;
  575. END RemoveFramesFromPanel;
  576. PROCEDURE AddFramesToPanel;
  577. VAR
  578. frameItem : FrameNode;
  579. BEGIN
  580. frameItem := firstFrame;
  581. WHILE frameItem # NIL DO
  582. AddContent(frameItem.panel);
  583. frameItem := frameItem.next;
  584. END;
  585. Resize();
  586. END AddFramesToPanel;
  587. PROCEDURE LoadLink(sender, data : ANY);
  588. VAR
  589. link, target, targetLow : String;
  590. BEGIN
  591. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.LoadLink, sender, data)
  592. ELSE
  593. DecodeLinkData(data, link, target);
  594. IF ~Strings.StartsWith2("#", link^) THEN
  595. targetLow := Strings.LowerCaseInNew(target^);
  596. IF (targetLow^ = "_parent") OR (targetLow^ = "_top") OR (targetLow^ = "_blank") THEN
  597. loadLink(NIL, data);
  598. ELSIF ~FindAndReloadFrame(link, target) THEN
  599. loadLink(NIL, data);
  600. END;
  601. END;
  602. END;
  603. END LoadLink;
  604. PROCEDURE FindAndReloadFrame(link, target : String) : BOOLEAN;
  605. VAR
  606. frameItem : FrameNode;
  607. framesetPanel : FramesetPanel;
  608. targetLow : String;
  609. url, dummyTitle : String;
  610. fWidth, fHeight : LONGINT;
  611. BEGIN
  612. frameItem := firstFrame;
  613. WHILE frameItem # NIL DO
  614. IF frameItem.name = NIL THEN
  615. (* frameItem is a frameset *)
  616. framesetPanel := frameItem.panel(FramesetPanel);
  617. IF framesetPanel.FindAndReloadFrame(link, target) THEN
  618. RETURN TRUE;
  619. END;
  620. ELSE
  621. (* frameItem is a frame *)
  622. targetLow := Strings.LowerCaseInNew(target^);
  623. IF (target^ = frameItem.name^) OR (targetLow^ = "_self") THEN
  624. RemoveFramesFromPanel();
  625. fWidth := GetFrameWidth(frameItem);
  626. fHeight := GetFrameHeight(frameItem);
  627. url := HTMLTransformer.ResolveAddress(baseAddress, link);
  628. frameItem.panel := GetContent(url, dummyTitle, fWidth, fHeight, frameItem.scrolling, LoadLink, frameItem.name);
  629. AlignFrame(frameItem);
  630. AddFramesToPanel;
  631. Reset(SELF, NIL);
  632. AlignSubComponents();
  633. Invalidate();
  634. RETURN TRUE;
  635. END;
  636. END;
  637. frameItem := frameItem.next;
  638. END;
  639. RETURN FALSE;
  640. END FindAndReloadFrame;
  641. END FramesetPanel;
  642. VAR
  643. frameNameCount : LONGINT;
  644. PROCEDURE GetContent(VAR url : String; VAR title : String; initWidth : LONGINT; initHeight : LONGINT; scrollbars : BOOLEAN; loadLink : WMEvents.EventListener; frameName : String) : VisualComponent;
  645. VAR
  646. rc : WebBrowserComponents.ResourceConnection;
  647. panel : VisualComponent;
  648. errorText : WebBrowserComponents.ShortText;
  649. image : WebBrowserComponents.StretchImagePanel;
  650. htmlPanel : HTMLPanel;
  651. textPanel : WebBrowserComponents.TextPanel;
  652. s : String;
  653. charset : String;
  654. charsetPos : SIZE;
  655. BEGIN
  656. rc := WebBrowserComponents.GetResourceConnection(url);
  657. IF rc = NIL THEN
  658. IF verbose THEN KernelLog.String("Not found: "); KernelLog.String(url^); KernelLog.Ln; END;
  659. s := Strings.ConcatToNew(" Not found: ", url^);
  660. NEW(errorText, s^);
  661. panel := errorText;
  662. ELSE
  663. url := rc.url;
  664. IF Strings.StartsWith2("text/html", rc.mimeType^) OR (rc.mimeType^ = "") THEN
  665. s := Strings.LowerCaseInNew(rc.mimeType^);
  666. IF Strings.Pos("charset", s^) >= 0 THEN
  667. charsetPos := Strings.IndexOfByte('=', charsetPos, rc.mimeType^) + 1;
  668. IF (charsetPos >= 0) & (charsetPos < Strings.Length(rc.mimeType^)) THEN
  669. charset := Strings.Substring2(charsetPos, rc.mimeType^);
  670. Strings.TrimWS(charset^);
  671. END;
  672. END;
  673. NEW(htmlPanel, title, rc, initWidth, initHeight, scrollbars, loadLink, charset, frameName);
  674. panel := htmlPanel;
  675. ELSIF Strings.StartsWith2("text/plain", rc.mimeType^) OR Strings.StartsWith2("application/xml", rc.mimeType^) THEN
  676. NEW(textPanel, rc, NIL);
  677. panel := textPanel;
  678. ELSIF Strings.StartsWith2("image/", rc.mimeType^) THEN
  679. NEW(image, rc, NIL, -1, -1);
  680. panel := image;
  681. ELSE
  682. IF verbose THEN KernelLog.String("Unknown content type: "); KernelLog.String(rc.mimeType^); KernelLog.Ln; END;
  683. s := Strings.ConcatToNew(" Unknown content type: ", rc.mimeType^);
  684. NEW(errorText, s^);
  685. panel := errorText;
  686. rc.Stop();
  687. rc.Release();
  688. END;
  689. END;
  690. RETURN panel;
  691. END GetContent;
  692. PROCEDURE DecodeLinkData*(data : ANY; VAR link : String; VAR target : String);
  693. VAR
  694. linkValue : String;
  695. urlPos, len : SIZE;
  696. BEGIN
  697. linkValue := data(WMTextView.LinkWrapper).link;
  698. IF Strings.StartsWith2("#", linkValue^) THEN
  699. link := linkValue;
  700. target := Strings.NewString("_self");
  701. ELSE
  702. urlPos := Strings.Pos(";url=", linkValue^);
  703. target := Strings.Substring(7, urlPos, linkValue^);
  704. len := Strings.Length(linkValue^);
  705. IF len > (urlPos + 5) THEN
  706. link := Strings.Substring(urlPos + 5, len, linkValue^);
  707. ELSE
  708. link := Strings.NewString("");
  709. END;
  710. END;
  711. END DecodeLinkData;
  712. PROCEDURE GetElement(name : ARRAY OF CHAR; root : XML.Element) : XML.Element;
  713. VAR
  714. rootName : String;
  715. contents: XMLObjects.Enumerator;
  716. content: ANY;
  717. retElement: XML.Element;
  718. BEGIN
  719. IF root = NIL THEN RETURN NIL; END;
  720. rootName := root.GetName();
  721. IF rootName^ = name THEN RETURN root; END;
  722. contents := root.GetContents();
  723. WHILE contents.HasMoreElements() & (retElement = NIL) DO
  724. content := contents.GetNext();
  725. IF content IS XML.Element THEN
  726. retElement := GetElement(name, content(XML.Element));
  727. END;
  728. END;
  729. RETURN retElement;
  730. END GetElement;
  731. PROCEDURE ParseFramesetAttr(frameset : XML.Element; VAR frameSlots : FrameslotNode; VAR frameborderSize : LONGINT; VAR fixSizes : LONGINT; VAR nodeIsCol : BOOLEAN);
  732. VAR
  733. s : String;
  734. rowsNode : FrameslotNode;
  735. colsNode : FrameslotNode;
  736. rowsCount : LONGINT;
  737. colsCount : LONGINT;
  738. rowsfixSizes : LONGINT;
  739. colsfixSizes : LONGINT;
  740. BEGIN
  741. rowsCount := 0;
  742. colsCount := 0;
  743. s := HTMLTransformer.GetElemAttributeValue(frameset, "rows", FALSE);
  744. IF s # NIL THEN
  745. ParseFramesetRowsOrCols(s, rowsNode, rowsCount, rowsfixSizes);
  746. END;
  747. s := HTMLTransformer.GetElemAttributeValue(frameset, "cols", FALSE);
  748. IF s # NIL THEN
  749. ParseFramesetRowsOrCols(s, colsNode, colsCount, colsfixSizes);
  750. END;
  751. IF (rowsCount = 0) & (colsCount = 0) THEN
  752. NEW(frameSlots);
  753. fixSizes := 0;
  754. nodeIsCol := FALSE;
  755. frameSlots.size := 100;
  756. frameSlots.type := typePercent;
  757. ELSIF rowsCount >= colsCount THEN
  758. frameSlots := rowsNode;
  759. fixSizes := rowsfixSizes;
  760. nodeIsCol := FALSE;
  761. ELSE
  762. frameSlots := colsNode;
  763. fixSizes := colsfixSizes;
  764. nodeIsCol := TRUE;
  765. END;
  766. (* frameborder-width *)
  767. frameborderSize := 6;
  768. s := HTMLTransformer.GetElemAttributeValue(frameset, "frameborder", FALSE);
  769. IF s # NIL THEN
  770. Strings.TrimWS(s^);
  771. Strings.StrToInt(s^, frameborderSize);
  772. ELSE
  773. s := HTMLTransformer.GetElemAttributeValue(frameset, "border", FALSE);
  774. IF s # NIL THEN
  775. Strings.TrimWS(s^);
  776. Strings.StrToInt(s^, frameborderSize);
  777. END;
  778. END;
  779. END ParseFramesetAttr;
  780. PROCEDURE ParseFramesetRowsOrCols(attrValue : String; VAR firstSlot : FrameslotNode; VAR nodeCount : LONGINT; VAR fixSizes : LONGINT);
  781. VAR
  782. start : SIZE;
  783. comma : SIZE;
  784. s : String;
  785. sizeStr : String;
  786. size : LONGINT;
  787. type : LONGINT;
  788. slotItem : FrameslotNode;
  789. lastSlot : FrameslotNode;
  790. prevSlot : FrameslotNode;
  791. percents : LONGINT;
  792. parts : LONGINT;
  793. factor : REAL;
  794. onePart : LONGINT;
  795. BEGIN
  796. percents := 0;
  797. parts := 0;
  798. fixSizes := 0;
  799. firstSlot := NIL;
  800. start := 0;
  801. REPEAT
  802. comma := Strings.IndexOfByte(',', start, attrValue^);
  803. IF comma = -1 THEN
  804. s := Strings.Substring2(start, attrValue^);
  805. ELSE
  806. s := Strings.Substring(start, comma, attrValue^);
  807. start := comma+1;
  808. END;
  809. Strings.TrimWS(s^);
  810. IF Strings.EndsWith("%", s^) THEN
  811. sizeStr := Strings.Substring(0, Strings.Length(s^)-1, s^);
  812. Strings.StrToInt(sizeStr^, size);
  813. type := typePercent;
  814. ELSIF Strings.EndsWith("*", s^) THEN
  815. IF Strings.Length(s^) = 1 THEN
  816. size := 1;
  817. ELSE
  818. sizeStr := Strings.Substring(0, Strings.Length(s^)-1, s^);
  819. Strings.TrimWS(sizeStr^);
  820. Strings.StrToInt(sizeStr^, size);
  821. END;
  822. type := typeParts;
  823. ELSE
  824. Strings.StrToInt(s^, size);
  825. type := typeFix;
  826. END;
  827. IF size > 0 THEN
  828. NEW(slotItem);
  829. slotItem.size := size;
  830. slotItem.type := type;
  831. IF type = typePercent THEN
  832. percents := percents + size;
  833. ELSIF type = typeParts THEN
  834. parts := parts + size;
  835. ELSE
  836. fixSizes := fixSizes + size;
  837. END;
  838. IF lastSlot # NIL THEN
  839. lastSlot.next := slotItem;
  840. lastSlot := slotItem;
  841. ELSE
  842. firstSlot := slotItem;
  843. lastSlot := slotItem;
  844. END;
  845. END;
  846. UNTIL comma = -1;
  847. IF (percents > 100) OR (parts = 0) THEN
  848. IF percents > 0 THEN
  849. factor := 100 / percents;
  850. END;
  851. onePart := 0;
  852. ELSE
  853. factor := 1;
  854. onePart := ENTIER((100 - percents) / parts);
  855. END;
  856. nodeCount := 0;
  857. slotItem := firstSlot;
  858. prevSlot := NIL;
  859. WHILE slotItem # NIL DO
  860. IF slotItem.type = typePercent THEN
  861. slotItem.size := ENTIER(slotItem.size * factor);
  862. ELSIF slotItem.type = typeParts THEN
  863. slotItem.size := slotItem.size * onePart;
  864. END;
  865. IF slotItem.size = 0 THEN
  866. IF prevSlot # NIL THEN
  867. prevSlot.next := slotItem.next;
  868. ELSE
  869. (* prevSlot remains NIL *)
  870. firstSlot := slotItem.next;
  871. END;
  872. ELSE
  873. INC(nodeCount);
  874. prevSlot := slotItem;
  875. END;
  876. slotItem := slotItem.next;
  877. END;
  878. END ParseFramesetRowsOrCols;
  879. PROCEDURE ParseFramesetContent(frameset : XML.Element; VAR first : FramesetNode);
  880. VAR
  881. last : FramesetNode;
  882. node : FramesetNode;
  883. enum : XMLObjects.Enumerator;
  884. p : ANY;
  885. frame : XML.Element;
  886. name : String;
  887. s : String;
  888. BEGIN
  889. first := NIL;
  890. last := NIL;
  891. enum := frameset.GetContents();
  892. WHILE enum.HasMoreElements() DO
  893. p := enum.GetNext();
  894. IF p IS XML.Element THEN
  895. frame := p(XML.Element);
  896. name := frame.GetName();
  897. IF name^ = "FRAMESET" THEN
  898. NEW(node);
  899. node.frameset := frame;
  900. IF last # NIL THEN
  901. last.next := node;
  902. last := node;
  903. ELSE
  904. first := node;
  905. last := node;
  906. END;
  907. ELSIF name^ = "FRAME" THEN
  908. s := HTMLTransformer.GetElemAttributeValue(frame, "src", FALSE);
  909. IF s # NIL THEN
  910. Strings.TrimWS(s^);
  911. IF s^ # "" THEN
  912. NEW(node);
  913. node.src := s;
  914. s := HTMLTransformer.GetElemAttributeValue(frame, "name", FALSE);
  915. IF s # NIL THEN
  916. Strings.TrimWS(s^);
  917. node.name := s;
  918. END;
  919. node.scrolling := TRUE;
  920. s := HTMLTransformer.GetElemAttributeValue(frame, "scrolling", TRUE);
  921. IF s # NIL THEN
  922. Strings.TrimWS(s^);
  923. IF s^ = "no" THEN
  924. node.scrolling := FALSE;
  925. END;
  926. END;
  927. IF last # NIL THEN
  928. last.next := node;
  929. last := node;
  930. ELSE
  931. first := node;
  932. last := node;
  933. END;
  934. END;
  935. END;
  936. END;
  937. END;
  938. END;
  939. END ParseFramesetContent;
  940. PROCEDURE GetNewFrameName() : String;
  941. VAR
  942. id : ARRAY 28 OF CHAR;
  943. nr : ARRAY 8 OF CHAR;
  944. BEGIN {EXCLUSIVE}
  945. id := "BimBrowser-Frame-ID-";
  946. Strings.IntToStr(frameNameCount, nr);
  947. Strings.Append(id, nr);
  948. INC(frameNameCount);
  949. RETURN Strings.NewString(id);
  950. END GetNewFrameName;
  951. BEGIN
  952. frameNameCount := 0;
  953. END WebBrowserPanel.