Syntax10.Scn.Fnt7pVersionElemsAllocBeg#Syntax10.Scn.FntPowerMac Windows LinuxPowerMacPowerMac Windows#Syntax10.Scn.FntVersion for WindowsLinux#Syntax10.Scn.FntVersion for LinuxpVersionElemsAllocEndInfoElemsAllocVSyntax10.Scn.FntStampElemsAlloc12 Oct 98/"Title": Web "Author": Andreas Krumenacker "Abstract": Web is a part of the Oberon-Web-Browser. "Keywords": internet, www "Version": no version "From": 4 Dez 97 "Until":  "Changes": no changes so far "Hints": no hints28FoldElemsNewSyntax10.Scn.FntSyntax10b.Scn.Fnt Syntax10i.Scn.Fnt   * $ ]    % j wildCard* = "*"; (* used to call default presentator *) anyPort* = 0; (* used for default port *) undefinedLen* = MAX(LONGINT); (* used, when filelength cannot be determined*) Omitted* = -2; Empty* = 0; Defined* = 1; Illegal* = -1; (* types for the parts of a netlocation *) Name* = 1; Number* = 2; (* additional types for the host of a netlocation; note that Defined and Name should be the same *) ident* = 1; diffFrag* = 0; different* = -1; (* results of an URL-comparison *) done* = 1; needData* = 0; error* = -1; reject* = -2; (* results of file-decoding *) default* = 0; store* = 1; show* = 2; (* desired actions, when opening an URL *) maxUrlLen* = 1024; urlStart = "URL:"; urlLowerLimit = 20X; urlUpperLimit = 7FX; schemeSep = ":"; netLocSep = "//"; passSep = ":"; portSep = ":"; pathSep = "/"; paramSep = ";"; querySep = "?"; fragSep = "#"; userSep = "@"; menuText = "^Web.Menu.Text"; profTextName = "Web.Profile"; profSect = "Web"; profMods = "modules"; profCods = "coders"; profGMT = "lackToGMT"; 88Syntax10.Scn.FntSyntax10b.Scn.Fnt  ! 8FoldElemsNew{Syntax10.Scn.FntSyntax10b.Scn.Fnt { ProfileEntryDesc* = RECORD class* : INTEGER; str* : ARRAY 64 OF CHAR; int* : LONGINT; next* : ProfileEntry; END;8(8mSyntax10.Scn.FntSyntax10b.Scn.Fnt  ,y LoaderDesc* = RECORD scheme* : SchemeId; defPort* : INTEGER; infoMeth* : ARRAY 16 OF CHAR; next : Loader; END;8   a8QSyntax10.Scn.FntSyntax10b.Scn.Fnt *O PresentatorDesc* = RECORD content* : ContentId; next : Presentator; END;8 Z8_Syntax10.Scn.FntSyntax10b.Scn.Fnt H ContentKeyDesc* = RECORD id* : ContentId; alt* : ContentKey; END;8 8Syntax10.Scn.FntSyntax10b.Scn.Fnt   netLocType- : INTEGER; userId- : UserId; userType- : INTEGER; password- : Password; pwType- : INTEGER; host- : Host; hostType- : INTEGER; port* : INTEGER; END;8Syntax10i.Scn.Fnt   8Syntax10.Scn.FntSyntax10b.Scn.Fnt   UrlDesc* = RECORD schemeId- : SchemeId; net* : NetLoc; path* : Path; params* : ParamInfo; query* : QueryInfo; frag* : FragmentId; END;898mSyntax10.Scn.FntSyntax10b.Scn.Fnt [ BodyDesc* = RECORD type* : ContentId; coding* : CodingId; file* : Files.File; END;88{Syntax10.Scn.FntSyntax10b.Scn.Fnt    M UrlStackDesc* = RECORD url* : Url; meth* : ARRAY 16 OF CHAR; body* : Body; org* : LONGINT; action : SHORTINT; prev : UrlStack; next : UrlStack; END;8 _8_Syntax10.Scn.FntSyntax10b.Scn.Fnt  C DocLengthDesc* = RECORD def* : LONGINT; act* : LONGINT; END;88Syntax10.Scn.FntSyntax10b.Scn.Fnt   FileInfoDesc* = RECORD r* : Files.Rider; len* : DocLength; local* : BOOLEAN; cKey* : ContentKey; coding* : CodingId; END;88mSyntax10.Scn.FntSyntax10b.Scn.Fnt  ,~ TaskDesc* = RECORD (Oberon.TaskDesc) cancelled- : BOOLEAN; txt* : Text; fi* : FileInfo; next, fwd, bck : Task; END;88{Syntax10.Scn.FntSyntax10b.Scn.Fnt  6 act* : UrlStack; base* : Url; cancelled* : BOOLEAN; loading- : BOOLEAN; display* : BOOLEAN; opened : BOOLEAN; tasks : Task; END;8&8#Syntax10.Scn.Fnt++ WatchDogDesc = RECORD txt : Text; END;8n8QSyntax10.Scn.FntSyntax10b.Scn.Fnt  %B EncoderDesc* = RECORD id* : CodingId; next : Encoder; END;8o8QSyntax10.Scn.FntSyntax10b.Scn.Fnt  %A DecoderDesc* = RECORD id* : CodingId; next : Decoder; END;8  8_Syntax10.Scn.FntSyntax10b.Scn.FntJ DecoderTaskDesc* = RECORD (TaskDesc) dest* : FileInfo; res* : INTEGER; act : UrlStack; elem : Texts.Elem; cod : Decoder; END;8w8CSyntax10.Scn.FntSyntax10b.Scn.Fnt <G FrameDesc* = RECORD(TextFrames.FrameDesc) watched : WatchDog; END;8N8#Syntax10.Scn.Fnt t : Texts.Text; END;8 ' 8CSyntax10.Scn.FntSyntax10b.Scn.Fnt &5 StateElemDesc* = RECORD (PopupElems.ElemDesc) END;8Y DynamicString* = POINTER TO ARRAY OF CHAR; ProfileEntry* = POINTER TO ProfileEntryDesc;  ParamLine = ARRAY maxUrlLen OF CHAR; SchemeId* = ARRAY 16 OF CHAR; Loader* = POINTER TO LoaderDesc;  ContentId* = ARRAY 64 OF CHAR; Presentator* = POINTER TO PresentatorDesc;  ContentKey* = POINTER TO ContentKeyDesc;  CodingId* = ARRAY 32 OF CHAR; UserId* = ARRAY 32 OF CHAR; Password* = ARRAY 32 OF CHAR; Host* = ARRAY 64 OF CHAR; NetLoc* = RECORD  Path* = ARRAY 256 OF CHAR; (* DynamicString might be better *) ParamInfo* = ARRAY 64 OF CHAR; (* DynamicString might be better *) QueryInfo* = DynamicString; FragmentId* = ARRAY 64 OF CHAR; (* DynamicString might be better *) Url* = POINTER TO UrlDesc;  Body* = POINTER TO BodyDesc;  UrlStack* = POINTER TO UrlStackDesc;  DocLength* = POINTER TO DocLengthDesc;  FileInfo* = POINTER TO FileInfoDesc;  Text* = POINTER TO TextDesc; Task* = POINTER TO TaskDesc;  TextDesc* = RECORD (Texts.TextDesc)  WatchDog = POINTER TO WatchDogDesc;  Encoder* = POINTER TO EncoderDesc;  Decoder* = POINTER TO DecoderDesc;  DecoderTask* = POINTER TO DecoderTaskDesc;  Frame* = POINTER TO FrameDesc;  TrackMsg* = RECORD (Display.FrameMsg) END; NeutralizeMsg = RECORD (Display.FrameMsg)  FileOpener* = PROCEDURE (path : ARRAY OF CHAR); StateElem* = POINTER TO StateElemDesc;  88CSyntax10.Scn.FntSyntax10b.Scn.Fnt  fileOpener* : FileOpener; urlUnsafe : ARRAY 24 OF CHAR; urlDelimiters : ARRAY 16 OF CHAR; urlIgnores, urlReserved : ARRAY 8 OF CHAR; profText : ARRAY 128 OF CHAR; searchName, foundPath : ARRAY 256 OF CHAR; firstLoader : Loader; firstPresentator, defPresentator : Presentator; firstEncoder : Encoder; firstDecoder : Decoder; firstStorer : Task; loadMod, loadCod : ProfileEntry; timeLack : INTEGER; SuperHandle : Display.Handler; trackedFrame : Frame; w : Texts.Writer; 8 Syntax10b.Scn.Fnt$8#Syntax10.Scn.Fnt VAR i : INTEGER; BEGIN i := 0; WHILE s[i] # 0X DO IF s[i] = "$" THEN Texts.WriteLn(w) ELSE Texts.Write(w, s[i]) END; INC(i) END; Texts.Append(Oberon.Log, w.buf) END LogStr;8M8#Syntax10.Scn.Fnt   VAR i, j : INTEGER; BEGIN i := 0; j := 0; WHILE s[i] # 0X DO IF s[i] = "$" THEN Texts.WriteLn(w) ELSIF s[i] = "#" THEN Texts.WriteInt(w, nums[j], 0); INC(j) ELSE Texts.Write(w, s[i]) END; INC(i) END; Texts.Append(Oberon.Log, w.buf) END LogFormStr;8 $8#Syntax10.Scn.FntLL VAR n : ARRAY 1 OF LONGINT; BEGIN n[0] := x; LogFormStr(s, n) END LogF;8 '8#Syntax10.Scn.FntXX VAR n : ARRAY 2 OF LONGINT; BEGIN n[0] := x; n[1] := y; LogFormStr(s, n) END LogF2;8 *{8#Syntax10.Scn.Fntcc VAR n : ARRAY 3 OF LONGINT; BEGIN n[0] := x; n[1] := y; n[2] := z; LogFormStr(s, n) END LogF3;8 -p8#Syntax10.Scn.Fntnn VAR n : ARRAY 4 OF LONGINT; BEGIN n[0] := w; n[1] := x; n[2] := y; n[3] := z; LogFormStr(s, n) END LogF4;8 8Syntax10.Scn.FntzpVersionElemsAllocBeg#Syntax10.Scn.FntPowerMac Windows LinuxPowerMacPowerMac Windows Linux WpVersionElemsAllocEnd# BEGIN CASE ord OF 196 : RETURN 128 (* *) | 214 : RETURN 129 (* *) | 220 : RETURN 130 (* *) | 224 : RETURN 139 (* *) | 225 : RETURN 148 (* *) | 226 : RETURN 134 (* *) | 228 : RETURN 131 (* *) | 231 : RETURN 147 (* *) | 232 : RETURN 140 (* *) | 233 : RETURN 144 (* *) | 234 : RETURN 135 (* *) | 235 : RETURN 145 (* *) | 236 : RETURN 141 (* *) | 238 : RETURN 136 (* *) | 239 : RETURN 146 (* *) | 241 : RETURN 149 (* *) | 242 : RETURN 142 (* *) | 244 : RETURN 137 (* *) | 246 : RETURN 132 (* *) | 249 : RETURN 143 (* *) | 251 : RETURN 138 (* *) | 252 : RETURN 133 (* *)  | 160 : RETURN 127 (* non breaking space *) | 223 : RETURN 167 (* german sharp s *)  ELSE RETURN ord END END CharMap;8 8Syntax10.Scn.FntzpVersionElemsAllocBeg#Syntax10.Scn.FntPowerMac Windows LinuxPowerMacPowerMac Windows Linux WpVersionElemsAllocEnd" BEGIN CASE ord OF 128 : RETURN 196 (* *) | 129 : RETURN 214 (* *) | 130 : RETURN 220 (* *) | 131 : RETURN 228 (* *) | 132 : RETURN 246 (* *) | 133 : RETURN 252 (* *) | 134 : RETURN 226 (* *) | 135 : RETURN 234 (* *) | 136 : RETURN 238 (* *) | 137 : RETURN 244 (* *) | 138 : RETURN 251 (* *) | 139 : RETURN 224 (* *) | 140 : RETURN 232 (* *) | 141 : RETURN 236 (* *) | 142 : RETURN 242 (* *) | 143 : RETURN 249 (* *) | 144 : RETURN 233 (* *) | 145 : RETURN 235 (* *) | 146 : RETURN 239 (* *) | 147 : RETURN 231 (* *) | 148 : RETURN 225 (* *) | 149 : RETURN 241 (* *)  | 127 : RETURN 160 (* non breaking space *) | 167 : RETURN 223 (* german sharp s *)  ELSE RETURN ord END END OrdMap;8K8#Syntax10.Scn.Fnt VAR ok : BOOLEAN; len, i : INTEGER; BEGIN ord := 0; len := Strings.Length (hex); IF hex[len - 1] = "H" THEN DEC (len) END; i := 0; ok := len = 2; WHILE (i < len) & ok DO ord := ord * 16; CASE hex[i] OF "0".."9" : INC (ord, ORD (hex[i]) - ORD ("0")); | "A".."F" : INC (ord, ORD (hex[i]) - ORD ("A") + 10); | "a".."f" : INC (ord, ORD (hex[i]) - ORD ("a") + 10); ELSE ok := FALSE END; INC (i) END; RETURN ok END HexStr2Ord;8K8#Syntax10.Scn.FntUU VAR ok : BOOLEAN; i : INTEGER; dig : ARRAY 2 OF INTEGER; BEGIN dig[0] := ord DIV 16; dig[1] := ord MOD 16; ok := dig[0] < 16; IF ok THEN FOR i := 0 TO 1 DO IF dig[i] <= 9 THEN hex[i] := CHR(ORD("0") + dig[i]) ELSE hex[i] := CHR(ORD("A") + dig[i] - 10) END END; hex[2] := 0X END; RETURN ok END Ord2HexStr;8  'T8#Syntax10.Scn.Fnt VAR ok : BOOLEAN; hex : ARRAY 3 OF CHAR; pos, ord : INTEGER; BEGIN ok := TRUE; pos := Strings.Pos ("%", str, 0); WHILE (pos >= 0) & ok DO Strings.Extract (str, pos + 1, 2, hex); ok := HexStr2Ord (hex, ord); IF ok THEN str[pos] := CHR (CharMap(ord)); INC (pos); Strings.Delete (str, pos, 2); pos := Strings.Pos ("%", str, pos) END END; RETURN ok; END StrDecoded;8  48#Syntax10.Scn.Fnt VAR hex : ARRAY 3 OF CHAR; ch : ARRAY 2 OF CHAR; pos : INTEGER; BEGIN pos := 0; ch[1] := 0X; ch[0] := str[pos]; WHILE ch[0] # 0X DO IF ((ORD(ch[0]) <= 31) OR (ORD(ch[0]) >= 127) OR (Strings.Pos(ch, urlUnsafe, 0) >= 0) OR (Strings.Pos(ch, urlReserved, 0) >= 0)) & (Strings.Pos(ch, doNot, 0) < 0) THEN IF Ord2HexStr (OrdMap(ORD(ch[0])), hex) THEN str[pos] := "%"; Strings.Insert (hex, pos + 1, str); INC(pos, 2) END END; INC(pos); ch[0] := str[pos] END END EncodeStr;8 "8CSyntax10.Scn.FntSyntax10i.Scn.Fnto" VAR int, help : LONGINT; len, sign, i : INTEGER; BEGIN int := 0; sign := 1; IF str[0] # 0X THEN len := Strings.Length (str); i := 0; WHILE (i < len) & (str[i] = 20X) DO INC (i) END; IF str[i] = "-" THEN sign := - 1; INC (i) END; WHILE (i < len) & (str[i] >= "0") & (str[i] <= "9") DO help := int * 10 + sign * (ORD (str[i]) - 30H); IF ((help < int) & (sign > 0)) OR ((help > int) & (sign < 0)) THEN (* overflow *) int := 0; i := len; ELSE int := help; END; INC (i); END; END; RETURN int; END Str2Int;8 +8CSyntax10.Scn.FntSyntax10i.Scn.Fnt,2 VAR val : LONGINT; max, i, j : INTEGER; BEGIN max := SHORT (LEN (str)) -1; IF int = MIN (LONGINT) THEN IF max > 10 THEN COPY ("-2147483648", str) ELSE str[0] := 0X END ELSE val := ABS (int); str[max] := 0X; i := max -1; REPEAT str[i] := CHR (30H + val MOD 10); val := val DIV 10; DEC (i); UNTIL (val = 0) OR (i < 0); IF i >= 0 THEN IF int < 0 THEN str[i] := "-" ELSE INC (i) END; FOR j := i TO max DO str[j-i] := str[j]; END; ELSIF (val > 0) OR (int < 0) THEN (* str is to short *) str[0] := 0X; END END END Int2Str;8A8#Syntax10.Scn.Fnt VAR i : INTEGER; ok : BOOLEAN; BEGIN i := Strings.Length (s) - 1; ok := i >= 0; WHILE ok & (i >= 0) DO IF (s[i] >= "A") & (s[i] <= "Z") THEN s[i] := CHR (ORD ("a") + ORD (s[i]) - ORD ("A")); ELSE ok := (s[i] >= "a") & (s[i] <= "z") OR (s[i] >= "0") & (s[i] <= "9"); ok := ok OR (s[i] = "+") OR (s[i] = ".") OR (s[i] = "-") END; DEC (i); END; IF ok THEN res := Defined ELSE s[0] := 0X; res := Empty END END CheckSchemeId;858eSyntax10.Scn.Fnt.j8FoldElemsNew#Syntax10.Scn.Fnttt VAR i : INTEGER; ok, per, hyph, top : BOOLEAN; BEGIN i := Strings.Length (h) - 1; ok := i >= 0; per := FALSE; hyph := FALSE; top := TRUE; WHILE ok & (i >= 0) DO IF (h[i] >= "A") & (h[i] <= "Z") OR (h[i] >= "a") & (h[i] <= "z") OR (h[i] >= "0") & (h[i] <= "9") THEN per := TRUE; hyph := TRUE; ELSIF h[i] = "." THEN ok := per & ~ (top & (h[i + 1] >= "0") & (h[i + 1] <= "9")); per := FALSE; hyph := FALSE; top := FALSE; ELSIF h[i] = "-" THEN ok := hyph & (i # 0); per := FALSE; ELSE ok := FALSE; END; DEC (i); END; RETURN ok; END HostIsName;808CSyntax10.Scn.FntSyntax10i.Scn.Fnth  (* Check, if host is a Number. *) (* A Number is a set of four decimal digit groups separated by periods. *) VAR perCount, i : INTEGER; ok, per : BOOLEAN; BEGIN i := Strings.Length (h) - 1; ok := i >= 0; per := FALSE; perCount := 0; WHILE ok & (i >= 0) DO IF (h[i] >= "0") & (h[i] <= "9") THEN per := TRUE; ELSIF h[i] = "." THEN INC (perCount); ok := per & (perCount < 4) & (i # 0); per := FALSE; ELSE ok := FALSE; END; DEC (i); END; RETURN ok; END HostIsNumber;8 PROCEDURE HostIsName (h : Host) : BOOLEAN;  PROCEDURE HostIsNumber (h : Host) : BOOLEAN;  BEGIN IF h[0] # 0X THEN IF HostIsNumber (h) THEN res := Number ELSIF HostIsName (h) THEN res := Name ELSE res := Illegal END; ELSE res := Empty; END END CheckHost;8 -P8#Syntax10.Scn.Fnt VAR portStr : ARRAY 8 OF CHAR; BEGIN IF actUrl # NIL THEN COPY (actUrl.schemeId, urlStr); IF actUrl.schemeId[0] # 0X THEN Strings.Append (schemeSep, urlStr) END; IF actUrl.net.netLocType # Omitted THEN Strings.Append (netLocSep, urlStr); IF actUrl.net.userType # Omitted THEN Strings.Append (actUrl.net.userId, urlStr); IF actUrl.net.pwType # Omitted THEN Strings.Append (passSep, urlStr); Strings.Append (actUrl.net.password, urlStr) END; Strings.Append (userSep, urlStr) END; Strings.Append (actUrl.net.host, urlStr); IF actUrl.net.port # anyPort THEN Strings.Append (portSep, urlStr); Int2Str (actUrl.net.port, portStr); Strings.Append (portStr, urlStr) END; END; Strings.Append (actUrl.path, urlStr); IF actUrl.params[0] # 0X THEN Strings.Append (paramSep, urlStr); Strings.Append (actUrl.params, urlStr) END; IF actUrl.query # NIL THEN Strings.Append (querySep, urlStr); Strings.Append (actUrl.query^, urlStr) END; IF actUrl.frag[0] # 0X THEN Strings.Append (fragSep, urlStr); Strings.Append (actUrl.frag, urlStr) END; ELSE urlStr[0] := 0X END END Url2Str;8 "D8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt VAR pos, num, len : INTEGER; BEGIN part[0] := 0X; res := Omitted; IF all[0] # 0X THEN pos := Strings.Pos(start, all, 0); len := Strings.Length(all); IF (pos >= 0) & (len - pos <= LEN(part)) THEN num := len - pos - 1; IF num > 0 THEN Strings.Extract(all, pos + Strings.Length(start), num, part); res := Defined ELSE res := Empty END; Strings.Delete(all, pos, num + 1) END END END SplitOffRightPart;8gp8#Syntax10.Scn.Fntnn VAR pos : INTEGER; BEGIN part[0] := 0X; res := Omitted; IF all[0] # 0X THEN pos := Strings.Pos(end, all, 0); IF (pos >= 0) & (pos < LEN(part)) THEN IF pos > 0 THEN Strings.Extract(all, 0, pos, part); res := Defined ELSE res := Empty END; Strings.Delete (all, 0, pos + Strings.Length(end)); END; END; END SplitOffLeftPart;868#Syntax10.Scn.Fnt33 VAR i, off : INTEGER; BEGIN i := 0; off := 0; WHILE str[off] = 20X DO INC(off) END; IF off > 0 THEN WHILE str[i+off] # 0X DO str[i] := str[i+off]; INC(i) END ELSE WHILE str[i] # 0X DO INC(i) END END; WHILE (i > 0) & (str[i-1] = 20X) DO DEC(i) END; str[i] := 0X END EatSurrBlanks;8NSyntax10i.Scn.FntF$ I VAR actUrl : Url; str, help : ARRAY maxUrlLen OF CHAR; pos, result : INTEGER; PROCEDURE SplitOffRightPart (start : ARRAY OF CHAR; VAR all, part : ARRAY OF CHAR; VAR res : INTEGER);  PROCEDURE SplitOffLeftPart (end : ARRAY OF CHAR; VAR all, part : ARRAY OF CHAR; VAR res : INTEGER);  PROCEDURE EatSurrBlanks (VAR str : ARRAY OF CHAR);  BEGIN EatSurrBlanks(urlStr); IF urlStr[0] # 0X THEN NEW (actUrl); (* parsing the fragment identifier *) SplitOffRightPart (fragSep, urlStr, actUrl.frag, result); (* parsing the scheme *) COPY (urlStr, str); SplitOffLeftPart (schemeSep, urlStr, actUrl.schemeId, result); IF result = Defined THEN CheckSchemeId (actUrl.schemeId, result); END; IF result = Empty THEN COPY (str, urlStr); END; (* parsing the network location / login *) actUrl.net.netLocType := Omitted; actUrl.net.userType := Omitted; actUrl.net.pwType := Omitted; actUrl.net.hostType := Omitted; actUrl.net.port := anyPort; (* not used: actUrl.net.userId[0] := 0X; actUrl.net.password[0] := 0X; actUrl.net.host[0] := 0X; *) IF Strings.Pos (netLocSep, urlStr, 0) = 0 THEN Strings.Delete (urlStr, 0, Strings.Length(netLocSep)); str[0] := 0X; pos := Strings.Pos (pathSep, urlStr, 0); IF pos > 0 THEN Strings.Extract (urlStr, 0, pos, str); Strings.Delete (urlStr, 0, pos); ELSIF pos < 0 THEN COPY (urlStr, str); urlStr[0] := 0X; END; IF str[0] = 0X THEN actUrl.net.netLocType := Empty ELSE actUrl.net.netLocType := Defined END; SplitOffLeftPart (userSep, str, actUrl.net.userId, actUrl.net.userType); SplitOffRightPart (passSep, actUrl.net.userId, actUrl.net.password, actUrl.net.pwType); COPY (str, actUrl.net.host); SplitOffRightPart (portSep, actUrl.net.host, str, result); actUrl.net.port := SHORT (Str2Int (str)); IF StrDecoded (actUrl.net.host) THEN CheckHost (actUrl.net.host, actUrl.net.hostType) ELSE actUrl.net.hostType := Illegal END END; (* parsing the query information *) SplitOffRightPart (querySep, urlStr, help, result); IF result = Defined THEN NEW(actUrl.query, Strings.Length(help) + 1); COPY(help, actUrl.query^) ELSE actUrl.query := NIL END; (* parsing the paramteters *) SplitOffRightPart (paramSep, urlStr, actUrl.params, result); (* parsing the path *) COPY (urlStr, actUrl.path); Url2Str(actUrl, urlStr); IF urlStr[0] # 0X THEN RETURN actUrl ELSE RETURN NIL END ELSE RETURN NIL END END Str2Url;8  8CSyntax10.Scn.FntSyntax10i.Scn.Fnt VAR empty : Url; BEGIN NEW (empty); empty.net.netLocType := Omitted; empty.net.userType := Omitted; empty.net.pwType := Omitted; empty.net.hostType := Omitted; empty.net.port := anyPort; (* not used: empty.frag[0] := 0X; empty.schemeId[0] := 0X; empty.net.userId[0] := 0X; empty.net.password[0] := 0X; empty.net.host[0] := 0X; empty.query := NIL empty.params[0] := 0X; empty.path[0] := 0X; *) RETURN empty END EmptyUrl;8 e8#Syntax10.Scn.Fntyy VAR i : INTEGER; str : ARRAY maxUrlLen OF CHAR; BEGIN Url2Str (url, str); LogStr("$"); IF str[0] # 0X THEN IF split THEN FOR i := 1 TO 30 DO Texts.Write(w, 9BX) END; Texts.Append(Oberon.Log, w.buf); LogStr("$") END; LogStr(str); IF split THEN IF url.schemeId[0] # 0X THEN LogStr("$ scheme: "); LogStr(url.schemeId) END; IF url.net.userType # Omitted THEN LogStr("$ userId: "); LogStr(url.net.userId) END; IF url.net.pwType # Omitted THEN LogStr("$ passw.: "); LogStr(url.net.password) END; IF url.net.hostType # Omitted THEN LogStr("$ host: "); LogStr(url.net.host); CASE url.net.hostType OF Number : LogStr(" (number)"); | Name : LogStr(" (name)"); | Illegal : LogStr(" (illegal)"); ELSE END END; IF url.net.port # anyPort THEN LogF("$ port: #", url.net.port) END; IF url.path[0] # 0X THEN LogStr("$ path: "); LogStr(url.path) END; IF url.params[0] # 0X THEN LogStr("$ params: "); LogStr(url.params) END; IF url.query # NIL THEN LogStr("$ query: "); LogStr(url.query^) END; IF url.frag[0] # 0X THEN LogStr("$ frag: "); LogStr(url.frag) END; LogStr("$"); FOR i := 1 TO 30 DO Texts.Write(w, 9BX) END; Texts.Append(Oberon.Log, w.buf); LogStr("$") END; LogStr("$") ELSE LogStr("the URL is empty$") END END LogUrl;8@ 8#Syntax10.Scn.Fnt VAR i : INTEGER; BEGIN IF url # NIL THEN COPY(url.path, path) END; i := Strings.Length (path); WHILE (i > 0) & (path[i - 1] # pathSep) DO DEC (i) END; path[i] := 0X END GetSolidPath;8  <8CSyntax10.Scn.FntSyntax10i.Scn.Fnt (* url- to oberon-convention *) VAR len, i : INTEGER; path : Path; dir : Directories.Directory; BEGIN IF url # NIL THEN COPY(url.path, path) ELSE COPY(name, path) END; len := Strings.Length(path); i := len; WHILE (i > 0) & (path[i - 1] # pathSep) DO DEC(i) END; IF i < len THEN IF withPath THEN IF path[0] = pathSep THEN Strings.Delete (path, 0, 1); DEC(i); DEC(len) END; DEC(i); WHILE (i >= 0) DO IF path[i] = pathSep THEN path[i] := Directories.delimiter END; DEC(i) END; ELSE Strings.Delete(path, 0, i) END ELSE path[0] := 0X END; IF ~ StrDecoded(path) THEN path[0] := 0X END; IF withPath THEN dir := Directories.Startup(); IF Strings.Pos(dir.path, path, 0) = 0 THEN len := Strings.Length(dir.path); Strings.Delete(path, 0, len); path[0] := "$" END END; len := Strings.Length(path); i := SHORT(LEN(name)) - 1; IF len > i THEN Strings.Extract(path, len - i, i, name); name[0] := "*" ELSE COPY(path, name) END END GetFileName;8 ' 8CSyntax10.Scn.FntSyntax10i.Scn.Fnt (* url- to oberon-convention *) VAR len, i : INTEGER; path : Path; BEGIN IF url # NIL THEN COPY(url.path, path) ELSE COPY(ext, path) END; len := Strings.Length (path); i := len; WHILE (i > 0) & (path[i - 1] # ".") & (path[i - 1] # pathSep) DO DEC (i) END; IF (i < len) & (path[i - 1] = ".") THEN Strings.Extract (path, i, len - i, ext) ELSE ext[0] := 0X END; IF ~ StrDecoded(ext) THEN ext[0] := 0X END END GetFileExtension;8  38CSyntax10.Scn.FntSyntax10i.Scn.Fnt/ (* find the menu frame of the frame containing txt *) VAR x : INTEGER; v : Viewers.Viewer; BEGIN x := 0; frame := NIL; IF txt # NIL THEN WHILE x < Display.Width DO v := Viewers.This(x, 0); WHILE (frame = NIL) & (v.state > 1) DO IF (v IS MenuViewers.Viewer) & (v.dsc.next IS TextFrames.Frame) & (v.dsc.next(TextFrames.Frame).text = txt) THEN frame := v.dsc(TextFrames.Frame) END; v := Viewers.Next(v) END; x := x + v.W END END END GetMenuFrame;8  3,8CSyntax10.Scn.FntSyntax10i.Scn.Fntq (* find the frame containing txt *) BEGIN GetMenuFrame(frame, txt); IF frame # NIL THEN frame := frame.next(TextFrames.Frame) END END GetFrame;8  ,8#Syntax10.Scn.Fnt\\ VAR frame : TextFrames.Frame; r : Texts.Reader; ch, start, stop : CHAR; beg, end : LONGINT; BEGIN start := 5BX; (* [ *) stop := 5DX; (* ] *) GetMenuFrame(frame, txt); IF frame # NIL THEN Texts.OpenReader(r, frame.text, 0); Texts.ReadElem(r); Texts.Read(r, ch); WHILE ~ r.eot & (ch # start) DO Texts.Read(r, ch) END; beg := Texts.Pos(r) - 1; Texts.Read(r, ch); WHILE ~ r.eot & (ch # stop) DO Texts.Read(r, ch) END; end := Texts.Pos(r); Texts.Read(r, ch); IF (ch = 20X) THEN INC(end) END; Texts.Delete(frame.text, beg, end); IF title # "" THEN Texts.Write(w, start); Texts.WriteString(w, title); Texts.Write(w, stop); Texts.Write(w, 20X); beg := frame.text.len - 1; Texts.OpenReader(r, frame.text, beg); Texts.Read(r, ch); IF ch # "!" THEN INC(beg) END; Texts.Insert(frame.text, beg, w.buf) END END END SetDocTitle;8  08#Syntax10.Scn.Fnt VAR frame : TextFrames.Frame; r : Texts.Reader; ch, start, stop : CHAR; i : INTEGER; BEGIN start := 5BX; (* [ *) stop := 5DX; (* ] *) i := 0; GetMenuFrame(frame, txt); IF frame # NIL THEN Texts.OpenReader(r, frame.text, 0); Texts.ReadElem(r); Texts.Read(r, ch); WHILE ~ r.eot & (ch # start) DO Texts.Read(r, ch) END; Texts.Read(r, ch); WHILE ~ r.eot & (ch # stop) DO title[i] := ch; INC(i); Texts.Read(r, ch) END; END; title[i] := 0X END GetDocTitle;8  +8#Syntax10.Scn.Fnt VAR frame : TextFrames.Frame; s : Texts.Scanner; pos : LONGINT; BEGIN pos := 0; GetMenuFrame(frame, txt); IF frame # NIL THEN Texts.OpenScanner(s, frame.text, 0); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN pos := Texts.Pos(s) - 1 END; Texts.Delete(frame.text, 0, pos); IF (name # "") & StrDecoded(name) THEN Texts.Write(w, '"'); Texts.WriteString(w, name); Texts.Write(w, '"'); Texts.Insert(frame.text, 0, w.buf) END END END SetDocName;8  C8#Syntax10.Scn.Fnt VAR frame : TextFrames.Frame; s : Texts.Scanner; i, j : INTEGER; BEGIN name[0] := 0X; GetMenuFrame(frame, txt); IF frame # NIL THEN Texts.OpenScanner(s, frame.text, 0); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN IF ~ withPath THEN i := 0; j := 0; WHILE s.s[i] # 0X DO IF (s.s[i] = Directories.delimiter) OR (s.s[i] = "$") THEN j := 0 ELSE name[j] := s.s[i]; INC(j) END; INC(i) END; name[j] := 0X ELSE COPY(s.s, name) END END END END GetDocName;8  8#Syntax10.Scn.Fnt__ VAR mod : Modules.Module; BEGIN IF (this # NIL) & (this = loadMod) THEN LogStr("Web 1.0 (AK)$") END; WHILE this # NIL DO IF this.class IN {Texts.Name, Texts.String} THEN mod := Modules.ThisMod(this.str); IF mod = NIL THEN LogStr('module "'); LogStr(this.str); LogStr('" not found$') END; END; this := this.next END; END LoadModules;8  8#Syntax10.Scn.Fnt VAR result : INTEGER; BEGIN IF ldr # NIL THEN CheckSchemeId (ldr.scheme, result); IF result # Empty THEN ldr.next := firstLoader; firstLoader := ldr; END; END END InstallLoader;838#Syntax10.Scn.Fnt VAR actLdr : Loader; port : INTEGER; BEGIN port := anyPort; actLdr := firstLoader; WHILE (actLdr # NIL) & (actLdr.scheme # id) DO actLdr := actLdr.next END; IF actLdr # NIL THEN port := actLdr.defPort END; RETURN port END DefaultPort;8E8#Syntax10.Scn.Fnt VAR actLdr : Loader; BEGIN meth[0] := 0X; actLdr := firstLoader; WHILE (actLdr # NIL) & (actLdr.scheme # id) DO actLdr := actLdr.next END; IF actLdr # NIL THEN COPY(actLdr.infoMeth, meth) END END GetInfoMethod;8838mSyntax10.Scn.FntCSyntax10i.Scn.Fnt0B5&3a CONST per = "."; dper = ".."; perSl = "./"; dperSl = "../"; TYPE Segment = ARRAY 64 OF CHAR; PList = POINTER TO PListDesc; PListDesc = RECORD seg : Segment; nextSeg : PList; prevSeg : PList; END; VAR start, list : PList; beg, pos : INTEGER; longPath : ARRAY maxUrlLen OF CHAR; BEGIN (* delete filename of base-path and append rel-path *) GetSolidPath(basep, NIL); IF basep = "" THEN basep := pathSep END; COPY(basep, longPath); Strings.Append (path, longPath); IF longPath[0] # 0X THEN (* build list of path segements and delete "./" and trailing period *) NEW (start); list := start; beg := 0; pos := Strings.Pos (pathSep, longPath, beg); WHILE pos >= 0 DO INC (pos); Strings.Extract (longPath, beg, pos - beg, list.seg); beg := pos; pos := Strings.Pos (pathSep, longPath, beg); IF list.seg # perSl THEN NEW (list.nextSeg); list.nextSeg.prevSeg := list; list := list.nextSeg; END; END; Strings.Extract (longPath, beg, Strings.Length (longPath) - beg, list.seg); IF (list.seg[0] = 0X) OR (list.seg = per) THEN list := list.prevSeg; list.nextSeg := NIL; END; (* apply backstep to parent directories *) list := start.nextSeg; WHILE list # NIL DO IF ((list.seg = dperSl) OR (list.seg = dper)) & (list.prevSeg # NIL) THEN IF (list.prevSeg.seg # dperSl) & (list.prevSeg.seg # pathSep) THEN IF list.nextSeg # NIL THEN list.nextSeg.prevSeg := list.prevSeg.prevSeg END; IF list.prevSeg.prevSeg # NIL THEN list.prevSeg.prevSeg.nextSeg := list.nextSeg ELSE start := list.nextSeg END END END; list := list.nextSeg; END; (* rebuild the path according to its list of segments *) path[0] := 0X; list := start; WHILE list # NIL DO Strings.Append (list.seg, path); list := list.nextSeg; END; END; END SetAbsPath;8=~8#Syntax10.Scn.Fnt`` BEGIN IF (base = NIL) & (txt # NIL) THEN IF txt.base # NIL THEN base := txt.base ELSIF txt.act # NIL THEN base := txt.act.url END END; IF base # NIL THEN IF url = NIL THEN NEW (url); url^ := base^ ELSIF (url.schemeId[0] = 0X) OR ((url.schemeId = base.schemeId) & (url.net.netLocType = Omitted)) THEN IF url.schemeId[0] = 0X THEN url.schemeId := base.schemeId END; IF url.net.netLocType = Omitted THEN url.net := base.net; IF url.path[0] # pathSep THEN IF url.path[0] = 0X THEN url.path := base.path; IF url.params[0] = 0X THEN url.params := base.params; IF (url.query = NIL) & (base.query # NIL) THEN NEW(url.query, LEN(base.query^)); COPY(base.query^, url.query^) END END ELSE SetAbsPath (url.path, base.path) END END END END END END Rel2Abs;8  .y8#Syntax10.Scn.Fntee VAR url : Url; BEGIN url := Str2Url(urlStr); Rel2Abs(url, NIL, txt); RETURN url END ResolvedUrl;8  )$8Syntax10.Scn.FntSyntax10i.Scn.Fnt"[8FoldElemsNew#Syntax10.Scn.FntUU BEGIN RETURN StrDecoded (str1) & StrDecoded (str2) & (str1 = str2) END EqualStr;8C]8#Syntax10.Scn.Fnt BEGIN IF (dStr1 # NIL) & (dStr2 # NIL) THEN RETURN EqualStr(dStr1^, dStr2^) ELSE RETURN dStr1 = dStr2 END END EqualDynStr;8Z" (* res = ident | diffFrag | different *) VAR defPort : INTEGER; PROCEDURE EqualStr (str1, str2 : ARRAY OF CHAR) : BOOLEAN;  PROCEDURE EqualDynStr (dStr1, dStr2 : DynamicString) : BOOLEAN;  BEGIN res := different; IF (url1 # NIL) & (url2 # NIL) & (url1.schemeId = url2.schemeId) & (url1.net.netLocType = url2.net.netLocType) & (url1.net.userType = url2.net.userType) & (url1.net.pwType = url2.net.pwType) & (url1.net.host = url2.net.host) & (url1.net.hostType = url2.net.hostType) & EqualStr (url1.net.userId, url2.net.userId) & EqualStr (url1.net.password, url2.net.password) & EqualStr (url1.path, url2.path) & EqualStr (url1.params, url2.params) & EqualDynStr (url1.query, url2.query) THEN defPort := DefaultPort(url1.schemeId); IF (url1.net.port = url2.net.port) OR ((url1.net.port = anyPort) & (url2.net.port = defPort)) OR ((url1.net.port = defPort) & (url2.net.port = anyPort)) THEN IF EqualStr (url1.frag, url2.frag) THEN res := ident ELSE res := diffFrag END END END END CompareUrls;8 88CSyntax10.Scn.FntSyntax10i.Scn.Fnt<  (* if long is set, also the scheme and netlocation are returned *) VAR frag : FragmentId; BEGIN IF url # NIL THEN IF long THEN frag := url.frag; url.frag := ""; Url2Str(url, rStr); url.frag := frag ELSE COPY (url.path, rStr); IF url.params[0] # 0X THEN Strings.Append (paramSep, rStr); Strings.Append (url.params, rStr) END; IF url.query # NIL THEN Strings.Append (querySep, rStr); Strings.Append (url.query^, rStr) END END ELSE rStr[0] := 0X END; END GetRequestStr;848CSyntax10.Scn.FntSyntax10i.Scn.Fnt3 (* count all tasks of the list, that are not cancelled *) VAR n : INTEGER; BEGIN n := 0; WHILE first # NIL DO IF ~ first.cancelled THEN INC(n) END; first := first.next END; RETURN n END CountActTasks;8B8#Syntax10.Scn.Fnt00 BEGIN IF state > 99 THEN COPY("99", name) ELSIF state <= 0 THEN COPY(" 0", name) ELSIF state > 9 THEN name[0] := CHR(30H + state DIV 10); name[1] := CHR(30H + state MOD 10); name[2] := 0X ELSE name[0] := 20X; name[1] := 20X; name[2] := CHR(30H + state); name[3] := 0X END END SetState;8  +V8#Syntax10.Scn.Fnt VAR e1 : StateElem; f : TextFrames.Frame; BEGIN WITH e : StateElem DO WITH m : Texts.CopyMsg DO IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(StateElem) END; PopupElems.Handle(e, m) | m : Texts.IdentifyMsg DO m.mod := "Web"; m.proc := "AllocState" | m : TextFrames.DisplayMsg DO IF m.prepare THEN e.name := " 0" ELSIF (m.frame.next # NIL) & (m.frame.next IS TextFrames.Frame) THEN f := m.frame.next(TextFrames.Frame); IF f.text IS Text THEN SetState(CountActTasks(f.text(Text).tasks), e.name) END END; PopupElems.Handle(e, m) ELSE PopupElems.Handle(e, m) END END END HandleState;8  8#Syntax10.Scn.Fnt]] VAR e : StateElem; BEGIN NEW(e); e.handle := HandleState; Texts.new := e END AllocState;8  8#Syntax10.Scn.FntLL VAR e : StateElem; insert : TextFrames.InsertElemMsg; BEGIN NEW(e); e.name := "0"; e.small := TRUE; e.handle := HandleState; e.menu := TextFrames.Text(""); Texts.WriteString(w, "Web.State"); Texts.WriteLn(w);Texts.Append(e.menu, w.buf); PopupElems.MeasureMenu(e); insert.e := e; Viewers.Broadcast(insert) END InsertState;8%8#Syntax10.Scn.Fnt VAR frame : TextFrames.Frame; r : Texts.Reader; task : Task; BEGIN GetMenuFrame(frame, txt); IF frame # NIL THEN Texts.OpenReader(r, frame.text, 0); Texts.ReadElem(r); WHILE r.elem # NIL DO IF r.elem IS StateElem THEN frame.text.notify(frame.text, Texts.replace, Texts.ElemPos(r.elem), Texts.ElemPos(r.elem) + 1) END; Texts.ReadElem(r) END END; txt.loading := FALSE; task := txt.tasks; WHILE ~ txt.loading & (task # NIL) DO txt.loading := ~ task.cancelled; task := task.next END END UpdateState;8 8#Syntax10.Scn.Fnt** VAR t, cT : Task; BEGIN IF (task # NIL) & (task.txt # NIL)THEN task.fwd := NIL; task.bck := NIL; t := task.txt.tasks; cT := NIL; WHILE (t # NIL) & (cT = NIL) DO IF ~ t.cancelled THEN IF t IS DecoderTask THEN IF t(DecoderTask).dest.len = task.fi.len THEN cT := t END ELSIF t.fi.len = task.fi.len THEN cT := t END END; t := t.next END; IF cT # NIL THEN cT.fwd := task; task.bck := cT END; task.cancelled := FALSE; task.next := task.txt.tasks; task.txt.tasks := task; UpdateState(task.txt) END END AddTask;8  8#Syntax10.Scn.Fnt VAR actTask : Task; BEGIN IF (task # NIL) THEN IF task.txt # NIL THEN actTask := task.txt.tasks ELSE actTask := firstStorer END; IF actTask = task THEN IF task.txt # NIL THEN task.txt.tasks := task.next ELSE firstStorer := task.next END ELSE WHILE (actTask # NIL) & (actTask.next # task) DO actTask := actTask.next END; IF actTask # NIL THEN actTask.next := task.next END END; IF (task.txt # NIL) & ~ task.cancelled THEN UpdateState(task.txt) END; task.next := NIL END END RemoveTask;858CSyntax10.Scn.FntSyntax10i.Scn.Fnt\ (* cancel all tasks of the text except that one with the specified file info and its companions *) VAR actTask, doNot, t : Task; BEGIN IF txt # NIL THEN IF fi # NIL THEN doNot := txt.tasks; WHILE (doNot # NIL) & (doNot.fi # fi) DO doNot := doNot.next END ELSE doNot := NIL END; actTask := txt.tasks; IF doNot = NIL THEN WHILE actTask # NIL DO actTask.cancelled := TRUE; actTask := actTask.next END; ELSE WHILE actTask # NIL DO t := actTask; WHILE (t # NIL) & (t # doNot) DO t := t.bck END; IF t = NIL THEN t := actTask; WHILE (t # NIL) & (t # doNot) DO t := t.fwd END END; actTask.cancelled := t = NIL; actTask := actTask.next END END; UpdateState(txt) END END CancelTasks;89K8#Syntax10.Scn.Fnt VAR i : INTEGER; BEGIN i := 0; WHILE (CAP(c1[i]) = CAP(c2[i])) & (c1[i] # 0X) DO INC(i) END; RETURN (c1[i] = 0X) & (c2[i] = 0X) END SameStrs;8 -8#Syntax10.Scn.Fnt BEGIN IF pres # NIL THEN pres.next := firstPresentator; firstPresentator := pres; IF pres.content = wildCard THEN defPresentator := pres END END END InstallPresentator;8WJ8#Syntax10.Scn.Fnt VAR pres : Presentator; BEGIN pres := NIL; WHILE (cKey # NIL) & (pres = NIL) DO pres := firstPresentator; WHILE (pres # NIL) & ~ SameStrs(pres.content, cKey.id) DO pres := pres.next END; IF pres = NIL THEN cKey := cKey.alt END END; IF (pres = NIL) & evenWild & (defPresentator # NIL) THEN NEW(cKey); cKey.id := wildCard; pres := defPresentator END; RETURN pres END ThisPresentator;8!B8#Syntax10.Scn.Fnt BEGIN HALT (99); END Open;8?8:Syntax10.Scn.FntM8FoldElemsNew#Syntax10.Scn.Fnt CONST default = "Web.Bin"; defBak = "Web.Bin.Bak"; VAR f : Files.File; res : INTEGER; BEGIN GetFileName(fName, FALSE, url); IF fName = "" THEN COPY(default, fName) ELSE f := Files.Old(fName); IF f # NIL THEN COPY(default, fName) END END; f := Files.Old(fName); IF f # NIL THEN Files.Rename(fName, defBak, res) END; f := Files.New(fName); RETURN f; END NewFile;8Syntax10i.Scn.Fnt# VAR rs : Files.Rider; fs, newF : Files.File; name : ARRAY 64 OF CHAR; buf : ARRAY 1024 OF CHAR; PROCEDURE NewFile (url : Url; VAR fName : ARRAY OF CHAR) : Files.File;  BEGIN IF ~ fi.local THEN fs := Files.Base(fi.r); Files.Close(fs); Files.Set(rs, fs, 0); newF := NewFile(url, name); IF newF # NIL THEN Files.Set(fi.r, newF, 0); WHILE ~ rs.eof DO Files.ReadBytes(rs, buf, 1024); Files.WriteBytes(fi.r, buf, 1024 - rs.res) END; Files.Register(newF); LogStr('storing file "'); LogStr(name); LogStr('"$'); IF t # NIL THEN RemoveTask(t); t.next := firstStorer; firstStorer := t; t.txt := NIL END ELSE fi.len.def := 0 (* force loader to quit *) END ELSE fi.len.def := 0 (* force loader to quit *) END END RegisterFile;8  B8mSyntax10.Scn.Fnt Syntax10i.Scn.FntR" $" VAR pres : Presentator; task, t : Task; evenWild : BOOLEAN; BEGIN IF (Oberon.CurTask # NIL) & (Oberon.CurTask IS Task) THEN task := Oberon.CurTask(Task); task.cancelled := TRUE; evenWild := (elem = NIL) & (fi.local OR (act.action = show)); IF task IS DecoderTask THEN (* called from Decoder *) t := task.fwd; WHILE t # NIL DO t.cancelled := TRUE; t := t.fwd END; (* cancel following tasks (fwd-chain) *) fi.cKey := NIL ELSE (* called from Presentator *) evenWild := evenWild & (task.fi.cKey.id # wildCard); task.fi.cKey := task.fi.cKey.alt END; pres := ThisPresentator(fi.cKey, evenWild); IF pres # NIL THEN pres.Open(act, txt, fi, elem) ELSE t := task; WHILE t.bck # NIL DO t.bck.cancelled := TRUE; t := t.bck END; (* cancel preceding tasks (bck-chain) *) IF (elem = NIL) & (act.action # show) THEN t.cancelled := FALSE; RegisterFile(act.url, t.fi, t) END END END END RejectFile;8 y8#Syntax10.Scn.Fntee BEGIN IF cod # NIL THEN cod.next := firstEncoder; firstEncoder := cod; END END InstallEncoder;88#Syntax10.Scn.Fnt BEGIN HALT (99); END Do;8  .8#Syntax10.Scn.Fnt'' VAR cod : Encoder; BEGIN IF (src # NIL) & (dest # NIL) THEN IF loadCod # NIL THEN LoadModules(loadCod); loadCod := NIL END; cod := firstEncoder; WHILE (cod # NIL) & ~ SameStrs (cod.id, coding) DO cod := cod.next END; IF cod # NIL THEN cod.Do(src, dest) END END END EncodeFile;8 y8#Syntax10.Scn.Fntee BEGIN IF cod # NIL THEN cod.next := firstDecoder; firstDecoder := cod; END END InstallDecoder;878#Syntax10.Scn.Fnt VAR cod : Decoder; BEGIN IF coding # "" THEN IF loadCod # NIL THEN LoadModules(loadCod); loadCod := NIL END; cod := firstDecoder; WHILE (cod # NIL) & ~ SameStrs (cod.id, coding) DO cod := cod.next END END; RETURN cod END ThisDecoder;8/8#Syntax10.Scn.Fnt BEGIN HALT (99); END Do;8  A;8#Syntax10.Scn.Fnt VAR cod : Decoder; BEGIN IF (src # NIL) & (dest # NIL) THEN cod := ThisDecoder (coding); IF cod # NIL THEN cod.Do(src, dest, res) END END END DecodeFile;88#Syntax10.Scn.Fnt BEGIN HALT (99); END DoTasked;8V8CSyntax10.Scn.FntSyntax10i.Scn.Fntch VAR thisTask : DecoderTask; prevPos, newPos : LONGINT; destFile : Files.File; quit : BOOLEAN; BEGIN thisTask := Oberon.CurTask(DecoderTask); prevPos := Files.Pos(thisTask.fi.r); IF thisTask.dest.len.def < undefinedLen THEN (* presentator terminated *) quit := TRUE; IF thisTask.dest.len.def = 0 THEN thisTask.fi.len.def := 0 ELSIF thisTask.fi.len.def = undefinedLen THEN thisTask.fi.len.def := prevPos END ELSE quit := thisTask.cancelled END; IF ~ quit THEN thisTask.cod.DoTasked(thisTask); newPos := Files.Pos(thisTask.fi.r); quit := thisTask.res # needData END; IF quit OR ((thisTask.fi.len.act >= 0) & (prevPos = newPos)) THEN IF thisTask.res = error THEN thisTask.fi.len.def := 0 ELSIF thisTask.res = reject THEN RejectFile(thisTask.fi, thisTask.act, thisTask.txt, thisTask.elem) ELSIF (thisTask.res = done) & (thisTask.fi.len.def = undefinedLen) THEN thisTask.fi.len.def := newPos END; destFile := Files.Base(thisTask.dest.r); Files.Close(destFile); thisTask.dest.len.act := Files.Length(destFile); RemoveTask(thisTask); Oberon.Remove(thisTask) END END Decode;88#Syntax10.Scn.Fnt66 BEGIN IF t = NIL THEN NEW(t) END END NewDecoderTask;8u8#Syntax10.Scn.Fnt++ VAR t : DecoderTask; BEGIN cod.NewDecoderTask(t); t.safe := FALSE; t.time := 0; t.handle := Decode; t.cancelled := FALSE; t.txt := txt; t.fi := src; t.dest := dest; t.res := needData; t.act := act; t.elem := elem; t.cod := cod; AddTask(t); Oberon.Install(t) END InstallDecoderTask;8 Al8Syntax10.Scn.Fntv8FoldElemsNew#Syntax10.Scn.Fnthh VAR new : FileInfo; BEGIN NEW(new); new.local := s.local; new.cKey := s.cKey; IF f = NIL THEN Files.Set(new.r, Files.Base(s.r), 0); new.len := s.len; new.coding := s.coding ELSE Files.Set(new.r, f, 0); NEW(new.len); new.len.def := undefinedLen; new.len.act := - 1; new.coding := "" END; RETURN new END NewFileInfo;8 Syntax10i.Scn.Fnt2]* VAR pres : Presentator; cod : Decoder; src, dest : FileInfo; t : Task; PROCEDURE NewFileInfo (s : FileInfo; f : Files.File) : FileInfo;  BEGIN IF (fi # NIL) & (fi.len # NIL) & (txt # NIL) & (act.url # NIL) THEN IF (Oberon.CurTask # NIL) & (Oberon.CurTask IS Task) & (Oberon.CurTask(Task).fi = fi) THEN t := Oberon.CurTask(Task) ELSE t := NIL END; IF act.action = store THEN RegisterFile(act.url, fi, t) ELSE (* find a proper presentator and decoder (if encoded) *) pres := ThisPresentator(fi.cKey, (elem = NIL) & (fi.local OR (act.action = show))); IF pres # NIL THEN src := NewFileInfo(fi, NIL); IF fi.coding # "" THEN cod := ThisDecoder(fi.coding); IF cod # NIL THEN dest := NewFileInfo(src, Files.New("")); InstallDecoderTask(cod, src, dest, act, txt, elem); src := NewFileInfo(dest, NIL) ELSIF (elem = NIL) & (fi.local OR (act.action = show)) & (defPresentator # NIL) THEN NEW(fi.cKey); fi.cKey.id := wildCard; src.cKey := fi.cKey; pres := defPresentator ELSE pres := NIL END END END; IF pres # NIL THEN IF elem = NIL THEN CancelTasks (txt, fi); txt.cancelled := TRUE END; pres.Open(act, txt, src, elem) ELSIF (elem = NIL) & (act.action # show) THEN RegisterFile(act.url, fi, t) ELSE fi.len.def := 0 (* force loader to quit *) END END END END OpenPresentator;8(j8#Syntax10.Scn.Fnttt VAR watched : WatchDog; BEGIN watched := SYS.VAL(WatchDog, obj); CancelTasks(watched.txt, NIL) END CancelText;8  18{Syntax10.Scn.FntCSyntax10b.Scn.Fnt v VAR f1 : Frame; control : Oberon.ControlMsg; BEGIN WITH m : NeutralizeMsg DO IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = m.t) THEN control.id := Oberon.neutralize; SuperHandle(f, control) END ELSE WITH f : Frame DO WITH m : Oberon.CopyMsg DO IF m.F = NIL THEN NEW(f1); m.F := f1 END; SuperHandle(f, m); m.F(Frame).watched := f.watched | m : Oberon.InputMsg DO IF (m.id = Oberon.track) & (m.keys# {}) THEN IF (1 IN m.keys) THEN trackedFrame := f ELSE trackedFrame := NIL END END; SuperHandle(f, m) | m : TrackMsg DO trackedFrame := f ELSE SuperHandle(f, m) END ELSE trackedFrame := NIL; SuperHandle(f, m) END END END FrameHandle;8  *;8#Syntax10.Scn.Fnt BEGIN TextFrames.Open(f, txt, pos); f.handle := FrameHandle; NEW(f.watched); f.watched.txt := txt; Kernel.RegisterObject(f.watched, CancelText) END OpenFrame;8 !8#Syntax10.Scn.Fnt66 VAR newTxt : Text; BEGIN NEW (newTxt); Texts.Open (newTxt, name); newTxt.notify := TextFrames.NotifyDisplay; newTxt.act := NIL; newTxt.base := NIL; newTxt.cancelled := FALSE; newTxt.loading := FALSE; newTxt.display := TRUE; newTxt.opened := FALSE; newTxt.tasks := NIL; RETURN newTxt END NewText;8 '8#Syntax10.Scn.Fnt]] VAR newF : Frame; BEGIN NEW(newF); OpenFrame(newF, txt, pos); RETURN newF END NewFrame;8&8#Syntax10.Scn.Fnt@@ VAR txtF : Frame; menF : TextFrames.Frame; view : MenuViewers.Viewer; x, y : INTEGER; BEGIN txtF := NewFrame(txt, 0); menF := TextFrames.NewMenu("", menuText); Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); view := MenuViewers.New(menF, txtF, TextFrames.menuH, x, y); txt.opened := TRUE END DisplayText;8 m8#Syntax10.Scn.Fntqq VAR m : NeutralizeMsg; BEGIN IF txt # NIL THEN m.t := txt; Viewers.Broadcast(m) END END NeutralizeText;8  8#Syntax10.Scn.Fnt BEGIN IF txt # NIL THEN IF ~ txt.opened & txt.display THEN DisplayText (txt) END; IF txt.cancelled THEN NeutralizeText(txt); Texts.Delete (txt, 0, txt.len); txt.cancelled := FALSE END END END ValidateText;8$o8#Syntax10.Scn.Fntoo VAR f : TextFrames.Frame; BEGIN GetFrame(f, txt); IF f # NIL THEN txt.act.org := f.org END END SetOrigin;8G8#Syntax10.Scn.Fnt BEGIN HALT (99); END Open;8q8#Syntax10.Scn.Fnt__ BEGIN IF name = searchName THEN COPY(d.path, foundPath); continue := FALSE END END CheckFile;8FA8#Syntax10.Scn.Fnt VAR dir : Directories.Directory; BEGIN dir := Directories.This(path); Directories.Enumerate(dir, CheckFile); continue := foundPath = "" END CheckPath;8Qf8#Syntax10.Scn.Fntxx VAR dir : Directories.Directory; BEGIN foundPath := ""; COPY(name, searchName); dir := Directories.Current(); Directories.Enumerate(dir, CheckFile); IF foundPath = "" THEN Directories.EnumeratePaths(CheckPath); IF foundPath = "" THEN dir := Directories.Startup(); Directories.Enumerate(dir, CheckFile); END END ; COPY(foundPath, absDir) END SearchOberonFile;8PJ8_Syntax10.Scn.FntQpVersionElemsAllocBeg#Syntax10.Scn.FntPowerMac Windows LinuxPowerMacPowerMac Windows#Syntax10.Scn.Fnt"..\"Linux#Syntax10.Scn.Fnt"../"pVersionElemsAllocEndSp#Syntax10.Scn.FntPowerMac Windows LinuxPowerMacPowerMac Windows#Syntax10.Scn.Fnt".\"Linux#Syntax10.Scn.Fnt"./"pXSyntax10i.Scn.Fnt@X CONST parent = "::"; current = ":"; VAR dir : Directories.Directory; i, j : INTEGER; BEGIN IF path[0] = "$" THEN (* rel path to startup *) Strings.Delete(path, 0, 1); dir := Directories.Startup(); COPY(dir.path, newPath) ELSIF Strings.Pos(parent, path, 0) = 0 THEN (* rel path to parent *) Strings.Delete(path, 0, Strings.Length(parent)); dir := Directories.Current(); COPY(dir.path, newPath); i := Strings.Length(newPath) - 1; WHILE (i > 0) & (newPath[i] # Directories.delimiter) DO DEC(i) END; newPath[i] := 0X ELSIF Strings.Pos(current, path, 0) = 0 THEN (* rel path to current *) Strings.Delete(path, 0, Strings.Length(current)); dir := Directories.Current(); COPY(dir.path, newPath) ELSIF Strings.Pos(Directories.delimiter, path, 0) < 0 THEN (* rel path => search *) SearchOberonFile(path, newPath) ELSE newPath[0] := 0X (* abs path *) END; i := -1; j := Strings.Length(newPath); IF (j > 0) & (newPath[j-1] # Directories.delimiter) THEN newPath[j] := Directories.delimiter; INC(j) END; REPEAT INC(i); newPath[i+j] := path[i] UNTIL path[i] = 0X END SetAbsFilePath;88#Syntax10.Scn.FntZZ VAR name : ARRAY 256 OF CHAR; BEGIN In.Open; In.Name(name); IF ~ In.Done THEN In.Open; In.String(name) END; IF In.Done THEN IF loadMod # NIL THEN LoadModules(loadMod); loadMod := NIL END; IF fileOpener # NIL THEN SetAbsFilePath(name, name); fileOpener(name) END ELSE LogStr("no opener for files installed$") END END OpenFile;8 78QSyntax10.Scn.FntSyntax10i.Scn.Fnt(N VAR r : Texts.Reader; beg, end, time : LONGINT; ch : ARRAY 2 OF CHAR; i : INTEGER; BEGIN i := 0; ch[1] := 0X; text := Oberon.Par.text; Texts.OpenReader (r, text, Oberon.Par.pos); Texts.Read (r, ch[0]); WHILE (ch = 20X) OR (Strings.Pos (ch, urlIgnores, 0) >= 0) DO Texts.Read (r, ch[0]) END; IF (ch = "^") THEN Oberon.GetSelection (text, beg, end, time); IF time >= 0 THEN Texts.OpenReader (r, text, beg); Texts.Read (r, ch[0]) END; END; (* now positioned on start of the parameter *) In.Open; In.String(urlStr); IF ~ In.Done THEN IF ch # "^" THEN (* ignore starting delimiters *) WHILE (Strings.Pos (ch, urlDelimiters, 0) >= 0) OR (Strings.Pos (ch, urlIgnores, 0) >= 0) OR (ch = 20X) DO Texts.Read (r, ch[0]) END; WHILE (i < LEN(urlStr) - 1) & (ch[0] # 0X) & (Strings.Pos (ch, urlDelimiters, 0) < 0) & (ch[0] >= urlLowerLimit) & (ch[0] <= urlUpperLimit) DO urlStr[i] := ch[0]; INC (i); Texts.Read (r, ch[0]) END END; urlStr[i] := 0X END END ScanUrl;81r8#Syntax10.Scn.Fntll VAR param : ParamLine; url : Url; text : Texts.Text; BEGIN ScanUrl(param, text); IF param # "" THEN IF Strings.Pos (urlStart, param, 0) = 0 THEN Strings.Delete (param, 0, Strings.Length(urlStart)) END; url := Str2Url(param); IF setAbs & (text IS Text) THEN Rel2Abs(url, NIL, text(Text)) END ELSE url := NIL END; RETURN url END ScannedUrl;8\8#Syntax10.Scn.Fnt VAR actLdr : Loader; BEGIN IF act.url # NIL THEN IF act.url.schemeId # "" THEN IF loadMod # NIL THEN LoadModules(loadMod); loadMod := NIL END; actLdr := firstLoader; WHILE (actLdr # NIL) & (actLdr.scheme # act.url.schemeId) DO actLdr := actLdr.next END; IF actLdr # NIL THEN actLdr.Open (act, txt, elem, useCache) ELSE LogStr('the protocol "'); LogStr(act.url.schemeId); LogStr('" is not supported.$') END ELSE LogStr("the scheme is missing$") END END END OpenAbsUrl;83H8#Syntax10.Scn.Fnt BEGIN WHILE src # NIL DO NEW(dest.prev); dest.prev^ := src^; dest.prev.next := dest; dest := dest.prev; src := src.prev END END PrependHistory;8 gs8#Syntax10.Scn.Fntkk VAR uStack : UrlStack; t : Text; BEGIN NEW(uStack); uStack.url := Str2Url(urlStr); COPY(meth, uStack.meth); uStack.body := body; uStack.org := 0; uStack.action := action; uStack.prev := NIL; uStack.next := NIL; IF (txt # NIL) & (txt IS Text) THEN t := txt(Text); IF elem = NIL THEN SetOrigin(t); IF action # store THEN PrependHistory(t.act, uStack) END END; Rel2Abs(uStack.url, NIL, t); OpenAbsUrl (uStack, t, elem, uStack.url.query = NIL) ELSE IF (elem = NIL) & (uStack.url # NIL) THEN IF (action # store) & (txt = NIL) & (trackedFrame # NIL) THEN t := trackedFrame.text(Text); Rel2Abs(uStack.url, NIL, t); Url2Str(uStack.url, urlStr); PrependHistory(t.act, uStack) END; LogStr('Web.Open "'); LogStr(urlStr); LogStr('"$'); END; OpenAbsUrl (uStack, NewText (""), elem, uStack.url.query = NIL) END END OpenUrl;8H8#Syntax10.Scn.Fnt// VAR url : Url; uStack : UrlStack; urlStr : ARRAY maxUrlLen OF CHAR; t : Texts.Text; BEGIN ScanUrl(urlStr, t); IF urlStr # "" THEN IF Strings.Pos (urlStart, urlStr, 0) = 0 THEN Strings.Delete (urlStr, 0, Strings.Length(urlStart)) END; url := Str2Url(urlStr); IF t IS Text THEN Rel2Abs(url, NIL, t(Text)); Url2Str(url, urlStr) END; IF url.schemeId # "" THEN NEW(uStack); uStack.url := url; uStack.meth[0] := 0X; uStack.body := NIL; uStack.org := 0; uStack.action := action; uStack.prev := NIL; uStack.next := NIL; IF (t IS Text) & (action # store) THEN PrependHistory(t(Text).act, uStack) END; LogStr(caller); LogStr(' "'); LogStr(urlStr); LogStr('"$'); OpenAbsUrl (uStack, NewText (""), NIL, uStack.url.query = NIL) ELSE OpenFile END END END OpenScannedUrl;8 8#Syntax10.Scn.Fnt55 BEGIN OpenScannedUrl(default, "Web.Open") END Open;8 8#Syntax10.Scn.Fnt;; BEGIN OpenScannedUrl(store, "Web.Download") END Download;8 8#Syntax10.Scn.Fnt VAR scannedUrl : Url; uStack : UrlStack; meth : ARRAY 16 OF CHAR; BEGIN scannedUrl := ScannedUrl(TRUE); IF scannedUrl # NIL THEN IF loadMod # NIL THEN LoadModules(loadMod); loadMod := NIL END; GetInfoMethod(scannedUrl.schemeId, meth); IF meth # "" THEN NEW(uStack); uStack.url := scannedUrl; COPY(meth, uStack.meth); uStack.body := NIL; uStack.org := 0; uStack.prev := NIL; uStack.next := NIL; OpenAbsUrl (uStack, NewText (""), NIL, FALSE) ELSE LogStr("no information available$") END END END GetInfo;8 8#Syntax10.Scn.Fnt VAR view : Viewers.Viewer; frame : Display.Frame; BEGIN frame := NIL; view := Oberon.Par.vwr; IF (Oberon.Par.frame IS TextFrames.Frame) & (Oberon.Par.frame = view.dsc) THEN frame := view.dsc.next ELSIF Oberon.Pointer.on THEN view := Oberon.MarkedViewer(); IF (view # NIL) & (view.dsc # NIL) & (view.dsc.next # NIL) THEN frame := view.dsc.next END END; IF (frame # NIL) & (frame IS TextFrames.Frame) THEN RETURN frame(TextFrames.Frame).text ELSE RETURN NIL END END TextOfMenuCmd;8"K8#Syntax10.Scn.Fnt VAR txt : Texts.Text; BEGIN txt := TextOfMenuCmd(); IF (txt # NIL) & (txt IS Text) THEN RETURN txt(Text) ELSE RETURN NIL END END TargetText;8  L8#Syntax10.Scn.Fnt VAR txt : Text; BEGIN txt := TargetText(); IF txt # NIL THEN txt.base := ScannedUrl(FALSE); LogUrl(txt.base, FALSE) END END SetBaseUrl;8  l8#Syntax10.Scn.Fntrr VAR txt : Text; BEGIN txt := TargetText(); IF txt # NIL THEN LogUrl(txt.base, FALSE) END END ShowBaseUrl;8 Y8#Syntax10.Scn.Fnt VAR txt : Text; BEGIN txt := TargetText(); IF (txt # NIL) & (txt.act # NIL) THEN LogUrl(txt.act.url, FALSE) END END ShowUrl;8 8#Syntax10.Scn.Fnt VAR txt : Text; BEGIN txt := TargetText(); IF (txt # NIL) & (txt.act # NIL) & (txt.act.prev # NIL) & (txt.act.prev.url # NIL) THEN CancelTasks(txt, NIL); SetOrigin(txt); OpenAbsUrl (txt.act.prev, txt, NIL, TRUE) END END Back;8 8#Syntax10.Scn.Fnt VAR txt : Text; BEGIN txt := TargetText(); IF (txt # NIL) & (txt.act # NIL) & (txt.act.next # NIL) & (txt.act.next.url # NIL) THEN CancelTasks(txt, NIL); SetOrigin(txt); OpenAbsUrl (txt.act.next, txt, NIL, TRUE) END END Forward;8 8#Syntax10.Scn.Fnt VAR txt : Text; BEGIN txt := TargetText(); IF (txt # NIL) & (txt.act # NIL) & (txt.act.url # NIL) THEN CancelTasks(txt, NIL); SetOrigin(txt); OpenAbsUrl (txt.act, txt, NIL, FALSE) END END Reload;8 v8#Syntax10.Scn.Fnthh VAR txt : Text; BEGIN txt := TargetText(); IF txt # NIL THEN CancelTasks(txt, NIL) END END Cancel;8 B8#Syntax10.Scn.Fnt VAR actTask : Task; BEGIN actTask := firstStorer; WHILE actTask # NIL DO actTask.cancelled := TRUE; actTask := actTask.next END END CancelDownload;8 8#Syntax10.Scn.Fnt VAR txt : Text; doc, store : INTEGER; BEGIN txt := TargetText(); IF txt # NIL THEN doc := CountActTasks(txt.tasks); UpdateState(txt) ELSE doc := 0 END; store := CountActTasks(firstStorer); LogF2("number of active tasks: # (+ # storing)$", doc, store) END State;8t8mSyntax10.Scn.FntSyntax10i.Scn.Fnt l VAR s : Texts.Scanner; ch : CHAR; found : BOOLEAN; BEGIN beg := 0; end := 0; found := FALSE; txt := TextFrames.Text(profText); IF txt.len > 0 THEN Texts.OpenScanner(s, txt, 0); REPEAT (* search section *) REPEAT Texts.Scan(s) UNTIL s.eot OR ((s.class = Texts.Char) & (s.c = "[")); IF ~ s.eot THEN Texts.Scan(s); found := (s.class = Texts.Name) & (s.s = sect) END UNTIL s.eot OR found; IF found THEN found := FALSE; REPEAT (* search item *) REPEAT Texts.Read(s, ch) UNTIL s.eot OR (ch = 0DX); Texts.OpenScanner(s, txt, Texts.Pos(s)); (* readjust scanner *) IF ~ s.eot THEN Texts.Scan(s); found := (s.class = Texts.Name) & (s.s = item) END UNTIL s.eot OR found OR ((s.class = Texts.Char) & (s.c = "[")) (* until found or other section *) END; IF found THEN Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "=") THEN REPEAT Texts.Read(s, ch) UNTIL s.eot OR ((ch # 20X) & (ch # 09X)); IF ~ s.eot THEN beg := Texts.Pos(s) - 1; end := beg; IF ~ s.eot & (ch # 0DX) & (ch # "~") THEN REPEAT Texts.Read(s, ch); INC(end) UNTIL s.eot OR (ch = 0DX) OR (ch = "~") END ELSE beg := txt.len - 1; end := beg END END END END; RETURN found END ProfileEntryFound;8  8#Syntax10.Scn.Fnt99 BEGIN RETURN TextFrames.Text(profText) END ProfileText;8  :z8#Syntax10.Scn.Fntdd VAR t : Texts.Text; s : Texts.Scanner; ent : ProfileEntry; beg, end : LONGINT; BEGIN IF ProfileEntryFound(sect, item, t, beg, end) & (end > beg) THEN t := TextFrames.Text(profText); Texts.OpenScanner(s, t, beg); NEW(entry); ent := entry; REPEAT Texts.Scan(s); NEW(ent.next); IF s.class IN {Texts.Name, Texts.String} THEN ent := ent.next; ent.class := s.class; COPY(s.s, ent.str); ELSIF s.class = Texts.Char THEN IF s.c # "~" THEN ent := ent.next; ent.class := s.class; ent.str[0] := s.c; ent.str[1] := 0X END ELSIF s.class = Texts.Int THEN ent := ent.next; ent.class := s.class; ent.int := s.i; ELSE ent := ent.next; ent.class := Texts.Inval; END UNTIL (Texts.Pos(s) > end) OR s.eot OR ((s.class = Texts.Char) & (s.c = "~")); ent.next := NIL; entry := entry.next ELSE entry := NIL END END GetProfile;8 8Syntax10.Scn.FntF8FoldElemsNew#Syntax10.Scn.FntBB VAR y, days : INTEGER; BEGIN IF mth = 2 THEN days := 28; y := yr; IF y < 50 THEN INC(y, 2000) ELSE INC(y, 1900) END; IF ((y MOD 4 = 0) & (y MOD 100 # 0)) OR (y MOD 400 = 0) THEN INC(days) END ELSE days := 30; IF mth IN {1, 3, 5, 7, 8, 10, 12} THEN INC(days) END END; RETURN days END MaxDays;8< VAR yr, mth, day, hr : INTEGER; PROCEDURE MaxDays () : INTEGER;  BEGIN Oberon.GetClock(t, d); hr := SHORT(t DIV 4096 MOD 32); hr := hr + timeLack; IF timeLack > 0 THEN IF hr >= 24 THEN DEC(hr, 24); day := SHORT(d MOD 32); INC(day); mth := SHORT(d DIV 32 MOD 16); yr := SHORT(d DIV 512 MOD 128); IF day > MaxDays() THEN day := 1; INC(mth); IF mth > 12 THEN mth := 1; INC(yr); END END; d := yr * 512 + mth * 32 + day END ELSIF timeLack < 0 THEN IF hr < 0 THEN INC(hr, 24); day := SHORT(d MOD 32); DEC(day); mth := SHORT(d DIV 32 MOD 16); yr := SHORT(d DIV 512 MOD 128); IF day < 1 THEN DEC(mth); IF mth < 1 THEN mth := 12; DEC(yr); END; day := MaxDays(); END; d := yr * 512 + mth * 32 + day END END; t := t MOD 4096 + LONG(hr) * 4096 END GetGMT;8=8#Syntax10.Scn.Fnt VAR prof : ProfileEntry; BEGIN fileOpener := NIL; urlDelimiters := "<>>'{}|\^~[]`"; urlDelimiters[2] := 22X; (* " *) COPY(urlDelimiters, urlUnsafe); urlUnsafe[13] := 20X; (* blank *) urlUnsafe[14] := 23X; (* # *) urlUnsafe[15] := 25X; (* % *) urlUnsafe[16] := 0X; urlReserved := ";/?:@=&"; urlIgnores[0] := 09X; (* tab *) urlIgnores[1] := 7FX; (* del *) urlIgnores[2] := 0X; firstLoader := NIL; firstPresentator := NIL; defPresentator := NIL; firstStorer := NIL; trackedFrame := NIL; Texts.OpenWriter(w); SetAbsFilePath(profTextName, profText); GetProfile(profSect, profMods, loadMod); GetProfile(profSect, profCods, loadCod); GetProfile(profSect, profGMT, prof); IF (prof # NIL) & (prof.class = Texts.Int) THEN timeLack := SHORT(prof.int); IF timeLack > 0 THEN timeLack := timeLack MOD 24 ELSIF timeLack < 0 THEN timeLack := - ABS(timeLack) MOD 24 END ELSE timeLack := 0 END END SetGlobalVars;88#Syntax10.Scn.FntXX SetGlobalVars(); HandlerElems.SetHandler("Web.FrameHandle", FrameHandle, SuperHandle)8 _MODULE Web; (* Version for PowerMac *)  IMPORT SYS := SYSTEM, Kernel, Oberon, Modules, Texts, TextFrames, MenuViewers, Viewers, Display, Directories, Files, In, Strings, PopupElems, HandlerElems; CONST  TYPE  VAR  PROCEDURE LogStr* (s : ARRAY OF CHAR);  PROCEDURE LogFormStr (VAR s : ARRAY OF CHAR; VAR nums : ARRAY OF LONGINT);  PROCEDURE LogF* (s : ARRAY OF CHAR; x : LONGINT);  PROCEDURE LogF2* (s : ARRAY OF CHAR; x, y : LONGINT);  PROCEDURE LogF3* (s : ARRAY OF CHAR; x, y, z : LONGINT);  PROCEDURE LogF4* (s : ARRAY OF CHAR; w, x, y, z : LONGINT);  PROCEDURE CharMap* (ord : INTEGER) : INTEGER;  PROCEDURE OrdMap* (ord : INTEGER) : INTEGER;  PROCEDURE HexStr2Ord (hex : ARRAY OF CHAR; VAR ord : INTEGER) : BOOLEAN;  PROCEDURE Ord2HexStr (ord : INTEGER; VAR hex : ARRAY OF CHAR) : BOOLEAN;  PROCEDURE StrDecoded* (VAR str : ARRAY OF CHAR) : BOOLEAN;  PROCEDURE EncodeStr* (VAR str : ARRAY OF CHAR; doNot : ARRAY OF CHAR);  PROCEDURE Str2Int* (str : ARRAY OF CHAR) : LONGINT;  PROCEDURE Int2Str* (int : LONGINT; VAR str : ARRAY OF CHAR);  PROCEDURE CheckSchemeId (VAR s : SchemeId; VAR res : INTEGER);  PROCEDURE CheckHost (h : Host; VAR res : INTEGER);  PROCEDURE Url2Str* (actUrl : Url; VAR urlStr : ARRAY OF CHAR);  PROCEDURE Str2Url* (urlStr : ARRAY OF CHAR) : Url;  PROCEDURE EmptyUrl* () : Url;  PROCEDURE LogUrl* (url : Url; split : BOOLEAN);  PROCEDURE GetSolidPath (VAR path : ARRAY OF CHAR; url : Url);  PROCEDURE GetFileName* (VAR name : ARRAY OF CHAR; withPath : BOOLEAN; url : Url);  PROCEDURE GetFileExtension* (VAR ext : ARRAY OF CHAR; url : Url);  PROCEDURE GetMenuFrame* (VAR frame : TextFrames.Frame; txt : Texts.Text);  PROCEDURE GetFrame* (VAR frame : TextFrames.Frame; txt : Texts.Text);  PROCEDURE SetDocTitle* (title : ARRAY OF CHAR; txt : Texts.Text);  PROCEDURE GetDocTitle* (VAR title : ARRAY OF CHAR; txt : Texts.Text);  PROCEDURE SetDocName* (name : ARRAY OF CHAR; txt : Texts.Text);  PROCEDURE GetDocName* (VAR name : ARRAY OF CHAR; withPath : BOOLEAN; txt : Texts.Text);  PROCEDURE LoadModules* (this : ProfileEntry);  PROCEDURE InstallLoader* (ldr : Loader);  PROCEDURE DefaultPort (id : SchemeId) : INTEGER;  PROCEDURE GetInfoMethod (id : SchemeId; VAR meth : ARRAY OF CHAR);  PROCEDURE SetAbsPath (VAR path : Path; basep : Path);  PROCEDURE Rel2Abs (VAR url : Url; base : Url; txt : Text);  PROCEDURE ResolvedUrl* (urlStr : ARRAY OF CHAR; txt : Text) : Url;  PROCEDURE CompareUrls* (url1, url2 : Url; VAR res : INTEGER);  PROCEDURE GetRequestStr* (url : Url; long : BOOLEAN; VAR rStr : ARRAY OF CHAR);  PROCEDURE CountActTasks (first : Task) : INTEGER;  PROCEDURE SetState(state : INTEGER; VAR name : ARRAY OF CHAR);  PROCEDURE HandleState* (e : Texts.Elem; VAR m : Texts.ElemMsg);  PROCEDURE AllocState*;  PROCEDURE InsertState*;  PROCEDURE UpdateState(txt : Text);  PROCEDURE AddTask* (task : Task);  PROCEDURE RemoveTask* (task : Task);  PROCEDURE CancelTasks (txt : Text; fi : FileInfo);  PROCEDURE SameStrs (c1, c2 : ARRAY OF CHAR) : BOOLEAN;  PROCEDURE InstallPresentator* (pres : Presentator);  PROCEDURE ThisPresentator (VAR cKey : ContentKey; evenWild : BOOLEAN) : Presentator;  PROCEDURE (pres : Presentator) Open* (act : UrlStack; txt : Text; fi : FileInfo; elem : Texts.Elem);  PROCEDURE RegisterFile (url : Url; fi : FileInfo; t : Task);  PROCEDURE RejectFile* (fi : FileInfo; act : UrlStack; txt : Text; elem : Texts.Elem);  PROCEDURE InstallEncoder* (cod : Encoder);  PROCEDURE (cod : Encoder) Do* (src, dest : Files.File);  PROCEDURE EncodeFile* (coding : CodingId; src, dest : Files.File);  PROCEDURE InstallDecoder* (cod : Decoder);  PROCEDURE ThisDecoder (coding : CodingId) : Decoder;  PROCEDURE (cod : Decoder) Do* (src, dest : Files.File; VAR res : INTEGER);  PROCEDURE DecodeFile* (coding : CodingId; src, dest : Files.File; VAR res : INTEGER);  PROCEDURE (cod : Decoder) DoTasked* (t : DecoderTask);  PROCEDURE Decode;  PROCEDURE (cod : Decoder) NewDecoderTask* (VAR t : DecoderTask);  PROCEDURE InstallDecoderTask (cod : Decoder; src, dest : FileInfo; act : UrlStack; txt : Text; elem : Texts.Elem);  PROCEDURE OpenPresentator* (fi : FileInfo; act : UrlStack; txt : Text; elem : Texts.Elem);  PROCEDURE CancelText (obj : SYS.PTR);  PROCEDURE FrameHandle* (f : Display.Frame; VAR m : Display.FrameMsg);  PROCEDURE OpenFrame* (f : Frame; txt : Text; pos : LONGINT);  PROCEDURE NewText* (name : ARRAY OF CHAR) : Text;  PROCEDURE NewFrame* (txt : Text; pos : LONGINT) : Frame;  PROCEDURE DisplayText (txt : Text);  PROCEDURE NeutralizeText* (txt : Texts.Text);  PROCEDURE ValidateText* (txt : Text);  PROCEDURE SetOrigin (txt : Text);  PROCEDURE (ldr : Loader) Open* (act : UrlStack; txt : Text; elem : Texts.Elem; useCache : BOOLEAN);  PROCEDURE CheckFile(d : Directories.Directory; name : ARRAY OF CHAR; isDir : BOOLEAN; VAR continue : BOOLEAN);  PROCEDURE CheckPath (path : ARRAY OF CHAR; VAR continue : BOOLEAN);  PROCEDURE SearchOberonFile (name : ARRAY OF CHAR; VAR absDir : ARRAY OF CHAR);  PROCEDURE SetAbsFilePath (path : ARRAY OF CHAR; VAR newPath : ARRAY OF CHAR);  PROCEDURE OpenFile;  PROCEDURE ScanUrl* (VAR urlStr : ARRAY OF CHAR; VAR text : Texts.Text);  PROCEDURE ScannedUrl (setAbs : BOOLEAN) : Url;  PROCEDURE OpenAbsUrl (act : UrlStack; txt : Text; elem : Texts.Elem; useCache : BOOLEAN);  PROCEDURE PrependHistory (src, dest : UrlStack);  PROCEDURE OpenUrl* (meth, urlStr : ARRAY OF CHAR; txt : Texts.Text; elem : Texts.Elem; body : Body; action : SHORTINT);  PROCEDURE OpenScannedUrl (action : SHORTINT; caller : ARRAY OF CHAR);  PROCEDURE Open*;  PROCEDURE Download*;  PROCEDURE GetInfo*;  PROCEDURE TextOfMenuCmd* () : Texts.Text;  PROCEDURE TargetText () : Text;  PROCEDURE SetBaseUrl*;  PROCEDURE ShowBaseUrl*;  PROCEDURE ShowUrl*;  PROCEDURE Back*;  PROCEDURE Forward*;  PROCEDURE Reload*;  PROCEDURE Cancel*;  PROCEDURE CancelDownload*;  PROCEDURE State*;  PROCEDURE ProfileEntryFound (sect, item : ARRAY OF CHAR; VAR txt : Texts.Text; VAR beg, end : LONGINT) : BOOLEAN;  PROCEDURE ProfileText* () : Texts.Text;  PROCEDURE GetProfile* (sect, item : ARRAY OF CHAR; VAR entry : ProfileEntry);  PROCEDURE GetGMT* (VAR t, d : LONGINT);  PROCEDURE SetGlobalVars;  BEGIN  END Web.