WebBrowser.Mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. MODULE WebBrowser; (** AUTHOR "Simon L. Keel"; PURPOSE "Simple Web Browser GUI"; *)
  2. IMPORT
  3. WebBrowserPanel,
  4. Strings, KernelLog, WMGraphics, WMComponents, WMStandardComponents, WMWindowManager, WMEditors,
  5. Modules, WMRestorable, XML, WMRectangles, WMMessages, Commands, Files;
  6. CONST
  7. HomePage = "http://bluebottle.ethz.ch";
  8. BrowserTitle = "BimBrowser";
  9. BookmarkPage = "file://bookmarks.html"; (* This URL is loaded when pressing the "Bookmarks"-button *)
  10. BookmarkFile = "bookmarks.html"; (* New bookmarks are appended to this file *)
  11. loadingNew = 0;
  12. loadingOld = 1;
  13. loadingNone = 2;
  14. TYPE
  15. String = Strings.String;
  16. URLNode = POINTER TO RECORD
  17. url, title : String;
  18. back, forward : URLNode;
  19. END;
  20. KillerMsg = OBJECT
  21. END KillerMsg;
  22. Window* = OBJECT (WMComponents.FormWindow)
  23. VAR
  24. webPanel : WebBrowserPanel.WebPanel;
  25. topToolbar : WMStandardComponents.Panel;
  26. urlEdit : WMEditors.Editor;
  27. back, forward, reload, home, bookm, addBM, go : WMStandardComponents.Button;
  28. loadID : LONGINT;
  29. actualURL : URLNode;
  30. PROCEDURE CreateForm() : WMComponents.VisualComponent;
  31. VAR
  32. panel : WMStandardComponents.Panel;
  33. BEGIN
  34. NEW(topToolbar); topToolbar.bounds.SetHeight(20); topToolbar.alignment.Set(WMComponents.AlignTop);
  35. NEW(panel); panel.bounds.SetExtents(1000, 650); panel.fillColor.Set(0FFFFFFFFH); panel.takesFocus.Set(TRUE);
  36. NEW(topToolbar); topToolbar.bounds.SetHeight(20); topToolbar.alignment.Set(WMComponents.AlignTop);
  37. panel.AddContent(topToolbar);
  38. NEW(back); back.caption.SetAOC("Back"); back.alignment.Set(WMComponents.AlignLeft);
  39. back.onClick.Add(Back);
  40. topToolbar.AddContent(back);
  41. NEW(forward); forward.caption.SetAOC("Forward"); forward.alignment.Set(WMComponents.AlignLeft);
  42. forward.onClick.Add(Forward);
  43. topToolbar.AddContent(forward);
  44. NEW(reload); reload.caption.SetAOC("Reload"); reload.alignment.Set(WMComponents.AlignLeft);
  45. reload.onClick.Add(Reload);
  46. topToolbar.AddContent(reload);
  47. NEW(home); home.caption.SetAOC("Home"); home.alignment.Set(WMComponents.AlignLeft);
  48. home.onClick.Add(Home);
  49. topToolbar.AddContent(home);
  50. NEW(bookm); bookm.caption.SetAOC("Bookmarks"); bookm.alignment.Set(WMComponents.AlignLeft);
  51. bookm.bounds.SetWidth(77);
  52. bookm.onClick.Add(Bookmarks);
  53. topToolbar.AddContent(bookm);
  54. NEW(addBM); addBM.caption.SetAOC("Add Bookmark"); addBM.alignment.Set(WMComponents.AlignLeft);
  55. addBM.bounds.SetWidth(97);
  56. addBM.onClick.Add(AddBookmark);
  57. topToolbar.AddContent(addBM);
  58. NEW(go); go.caption.SetAOC("Go"); go.alignment.Set(WMComponents.AlignRight);
  59. go.onClick.Add(Go);
  60. topToolbar.AddContent(go);
  61. NEW(urlEdit); urlEdit.alignment.Set(WMComponents.AlignClient);
  62. urlEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  63. urlEdit.multiLine.Set(FALSE); urlEdit.bounds.SetWidth(500);
  64. topToolbar.AddContent(urlEdit); urlEdit.fillColor.Set(0FFFFFFFFH);
  65. urlEdit.tv.showBorder.Set(TRUE);
  66. urlEdit.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  67. urlEdit.onEnter.Add(Go);
  68. NEW(webPanel);
  69. webPanel.alignment.Set(WMComponents.AlignClient);
  70. panel.AddContent(webPanel);
  71. webPanel.notify := Notify;
  72. webPanel.openNewWindow := OpenLinkFromString;
  73. webPanel.loadLink := LoadExternal;
  74. RETURN panel
  75. END CreateForm;
  76. PROCEDURE &New*(c : WMRestorable.Context; url : String);
  77. VAR
  78. vc : WMComponents.VisualComponent;
  79. xml : XML.Element;
  80. m : WMWindowManager.WindowManager;
  81. indent : LONGINT;
  82. BEGIN
  83. IncCount;
  84. loadID := 0;
  85. vc := CreateForm();
  86. Init(vc.bounds.GetWidth(), vc.bounds.GetHeight(), FALSE);
  87. SetContent(vc);
  88. SetIcon(WMGraphics.LoadImage("WMIcons.tar://WebBrowser.png", TRUE));
  89. IF c # NIL THEN
  90. (* restore the desktop *)
  91. WMRestorable.AddByContext(SELF, c);
  92. IF c.appData # NIL THEN
  93. xml := c.appData(XML.Element);
  94. url := xml.GetAttributeValue("url");
  95. Resized(GetWidth(), GetHeight())
  96. END
  97. ELSE
  98. WMWindowManager.DefaultAddWindow(SELF);
  99. indent := leftW.bounds.r;
  100. IF topW.bounds.b > indent THEN indent := topW.bounds.b; END;
  101. m := GetManager();
  102. m.SetWindowPos(SELF, (nofWindows-1) * indent + leftW.bounds.r, (nofWindows-1) * indent + topW.bounds.b);
  103. END;
  104. IF url = NIL THEN
  105. url := Strings.NewString(HomePage);
  106. END;
  107. NEW(actualURL);
  108. actualURL.url := Strings.NewString(url^);
  109. Load();
  110. END New;
  111. PROCEDURE Load;
  112. VAR
  113. s : String;
  114. BEGIN
  115. urlEdit.SetAsString(actualURL.url^);
  116. IF actualURL.title = NIL THEN
  117. SetTitle(Strings.NewString(BrowserTitle));
  118. ELSE
  119. s := Strings.ConcatToNew(actualURL.title^, " - ");
  120. s := Strings.ConcatToNew(s^, BrowserTitle);
  121. SetTitle(s);
  122. END;
  123. webPanel.url.Set(actualURL.url);
  124. webPanel.Load(loadID);
  125. loadID := (loadID + 1) MOD (MAX(LONGINT));
  126. END Load;
  127. PROCEDURE Go(sender, data : ANY);
  128. VAR
  129. urlNode : URLNode;
  130. urlAOC : ARRAY 1024 OF CHAR;
  131. i: SIZE;
  132. BEGIN
  133. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Go, sender, data)
  134. ELSE
  135. NEW(urlNode);
  136. urlEdit.GetAsString(urlAOC);
  137. i := Strings.Pos("://", urlAOC);
  138. IF i = -1 THEN
  139. urlNode.url := Strings.ConcatToNew("http://", urlAOC);
  140. ELSE
  141. urlNode.url := Strings.NewString(urlAOC);
  142. END;
  143. actualURL.forward := urlNode;
  144. urlNode.back := actualURL;
  145. actualURL := urlNode;
  146. Load();
  147. END;
  148. END Go;
  149. PROCEDURE Back(sender, data : ANY);
  150. BEGIN
  151. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Back, sender, data)
  152. ELSE
  153. IF actualURL.back # NIL THEN
  154. actualURL := actualURL.back;
  155. Load();
  156. END;
  157. END;
  158. END Back;
  159. PROCEDURE Forward(sender, data : ANY);
  160. BEGIN
  161. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Forward, sender, data)
  162. ELSE
  163. IF actualURL.forward # NIL THEN
  164. actualURL := actualURL.forward;
  165. Load();
  166. END;
  167. END;
  168. END Forward;
  169. PROCEDURE Reload(sender, data : ANY);
  170. BEGIN
  171. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Reload, sender, data)
  172. ELSE
  173. Load();
  174. END;
  175. END Reload;
  176. PROCEDURE Home(sender, data : ANY);
  177. VAR
  178. urlNode : URLNode;
  179. BEGIN
  180. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Home, sender, data)
  181. ELSE
  182. NEW(urlNode);
  183. urlNode.url := Strings.NewString(HomePage);
  184. actualURL.forward := urlNode;
  185. urlNode.back := actualURL;
  186. actualURL := urlNode;
  187. Load();
  188. END;
  189. END Home;
  190. PROCEDURE Bookmarks(sender, data : ANY);
  191. VAR
  192. urlNode : URLNode;
  193. BEGIN
  194. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Bookmarks, sender, data)
  195. ELSE
  196. NEW(urlNode);
  197. urlNode.url := Strings.NewString(BookmarkPage);
  198. actualURL.forward := urlNode;
  199. urlNode.back := actualURL;
  200. actualURL := urlNode;
  201. Load();
  202. END;
  203. END Bookmarks;
  204. PROCEDURE LoadExternal*(sender, data : ANY);
  205. VAR
  206. link, target : String;
  207. urlNode : URLNode;
  208. BEGIN
  209. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.LoadExternal, sender, data)
  210. ELSE
  211. WebBrowserPanel.DecodeLinkData(data, link, target);
  212. NEW(urlNode);
  213. urlNode.url := Strings.NewString(link^);
  214. actualURL.forward := urlNode;
  215. urlNode.back := actualURL;
  216. actualURL := urlNode;
  217. Load();
  218. END;
  219. END LoadExternal;
  220. PROCEDURE Notify(sender, data : ANY);
  221. VAR
  222. msg : WebBrowserPanel.NotifyMsg;
  223. s : String;
  224. BEGIN
  225. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.Notify, sender, data)
  226. ELSE
  227. IF loadID # SELF.loadID THEN RETURN END;
  228. msg := data(WebBrowserPanel.NotifyMsg);
  229. IF msg.url # NIL THEN
  230. actualURL.url := Strings.NewString(msg.url^);
  231. urlEdit.SetAsString(actualURL.url^);
  232. END;
  233. IF (msg.title # NIL) & (msg.title^ # "") THEN
  234. actualURL.title := Strings.NewString(msg.title^);
  235. s := Strings.ConcatToNew(actualURL.title^, " - ");
  236. s := Strings.ConcatToNew(s^, BrowserTitle);
  237. SetTitle(s);
  238. END;
  239. END;
  240. END Notify;
  241. PROCEDURE AddBookmark(sender, data : ANY);
  242. BEGIN
  243. IF ~IsCallFromSequencer() THEN sequencer.ScheduleEvent(SELF.AddBookmark, sender, data)
  244. ELSE
  245. IF actualURL.title # NIL THEN
  246. AddBookmarkToFile(actualURL.url^, actualURL.title^);
  247. ELSE
  248. AddBookmarkToFile(actualURL.url^, actualURL.url^);
  249. END;
  250. END;
  251. END AddBookmark;
  252. PROCEDURE Close*;
  253. BEGIN
  254. webPanel.notify := NIL;
  255. webPanel.openNewWindow := NIL;
  256. webPanel.loadLink := NIL;
  257. Close^;
  258. DecCount
  259. END Close;
  260. PROCEDURE Handle*(VAR x: WMMessages.Message);
  261. VAR
  262. data : XML.Element;
  263. a : XML.Attribute;
  264. n : ARRAY 16 OF CHAR;
  265. BEGIN
  266. IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) THEN
  267. IF (x.ext IS KillerMsg) THEN Close
  268. ELSIF (x.ext IS WMRestorable.Storage) THEN
  269. NEW(data); n := "WebBrowserData"; data.SetName(n);
  270. NEW(a); n := "url"; a.SetName(n); a.SetValue(actualURL.url^); data.AddAttribute(a);
  271. x.ext(WMRestorable.Storage).Add("WebBrowser", "WebBrowser.Restore", SELF, data)
  272. ELSE Handle^(x)
  273. END
  274. ELSE Handle^(x)
  275. END
  276. END Handle;
  277. END Window;
  278. VAR
  279. nofWindows : LONGINT;
  280. PROCEDURE AddBookmarkToFile(CONST link : ARRAY OF CHAR; title : ARRAY OF CHAR);
  281. VAR
  282. file : Files.File;
  283. w : Files.Writer;
  284. BEGIN
  285. Strings.TrimWS(title);
  286. file := Files.Old(BookmarkFile);
  287. IF file = NIL THEN
  288. file := Files.New(BookmarkFile);
  289. IF file = NIL THEN
  290. KernelLog.String("Writing "); KernelLog.String(BookmarkFile); KernelLog.String(" failed."); KernelLog.Ln;
  291. RETURN;
  292. END;
  293. Files.OpenWriter(w, file, 0);
  294. w.String('<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">'); w.Ln();
  295. w.String("<TITLE>Bookmarks</TITLE>"); w.Ln();
  296. w.String("<H1>Bookmarks</H1>"); w.Ln();
  297. w.Ln();
  298. w.String("<DL><P>"); w.Ln();
  299. ELSE
  300. Files.OpenWriter(w, file, file.Length());
  301. END;
  302. w.String(' <DT><A HREF="');
  303. w.String(link);
  304. w.String('">');
  305. w.String(title);
  306. w.String('</A>');
  307. w.Ln();
  308. w.Update();
  309. Files.Register(file);
  310. file.Update;
  311. END AddBookmarkToFile;
  312. PROCEDURE Open*;
  313. VAR inst : Window;
  314. BEGIN
  315. NEW(inst, NIL, NIL);
  316. END Open;
  317. PROCEDURE OpenURL*(context : Commands.Context);
  318. VAR inst : Window; name : ARRAY 1024 OF CHAR;
  319. BEGIN
  320. IF context.arg.GetString(name) THEN
  321. NEW(inst, NIL, Strings.NewString(name));
  322. END;
  323. END OpenURL;
  324. PROCEDURE OpenFile*(context : Commands.Context);
  325. VAR inst : Window; prefix, name, path : ARRAY 1024 OF CHAR; urlpath, url : String; i,j:LONGINT;
  326. BEGIN
  327. IF context.arg.GetString(name) THEN
  328. Files.SplitName(name, prefix, path);
  329. j:=0;
  330. FOR i:=0 TO Strings.Length(path)-1 DO
  331. IF path[i]#" " THEN name[j]:=path[i]
  332. ELSE name[j]:="%"; name[j+1]:="2"; name[j+2]:="0"; INC(j,2);
  333. END;
  334. INC(j);
  335. END;
  336. name[j]:=0X;
  337. path:="file://";
  338. IF prefix#"" THEN Strings.Append(path,prefix); Strings.Append(path,":"); END;
  339. url := Strings.ConcatToNew(path, name);
  340. NEW(inst, NIL, url);
  341. END;
  342. END OpenFile;
  343. PROCEDURE OpenLinkFromString*(url : String);
  344. VAR inst : Window;
  345. BEGIN
  346. NEW(inst, NIL, url);
  347. END OpenLinkFromString;
  348. PROCEDURE Restore*(context : WMRestorable.Context);
  349. VAR w : Window;
  350. BEGIN
  351. NEW(w, context, NIL)
  352. END Restore;
  353. PROCEDURE IncCount;
  354. BEGIN {EXCLUSIVE}
  355. INC(nofWindows)
  356. END IncCount;
  357. PROCEDURE DecCount;
  358. BEGIN {EXCLUSIVE}
  359. DEC(nofWindows)
  360. END DecCount;
  361. PROCEDURE Cleanup;
  362. VAR die : KillerMsg;
  363. msg : WMMessages.Message;
  364. m : WMWindowManager.WindowManager;
  365. BEGIN {EXCLUSIVE}
  366. NEW(die); msg.ext := die; msg.msgType := WMMessages.MsgExt;
  367. m := WMWindowManager.GetDefaultManager();
  368. m.Broadcast(msg);
  369. AWAIT(nofWindows = 0)
  370. END Cleanup;
  371. BEGIN
  372. Modules.InstallTermHandler(Cleanup);
  373. END WebBrowser.
  374. PC.Compile \s WMCharCodes.Mod NewHTTPClient.Mod Strings.Mod WebBrowserComponents.Mod XMLTransformer.Mod HTMLTransformer.Mod HTMLScanner.Mod HTMLParser.Mod WebBrowserPanel.Mod WebBrowser.Mod~
  375. System.Free WebBrowser WebBrowserPanel HTMLParser HTMLScanner HTMLTransformer XMLTransformer WebBrowserComponents Utilities NewHTTPClient WMCharCodes~
  376. WebBrowser.Open ~
  377. WebBrowser.OpenURL http://www.google.com ~
  378. WebBrowser.OpenURL http://www.wikipedia.org~
  379. WebBrowser.OpenURL http://www.wikipedia.org/wiki/man ~
  380. WebBrowser.OpenFile OberonReport.html ~