Oberon/A2/Oberon.QuotedPrintable.Mod

< Oberon‎ | A2
(* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich.
Refer to the "General ETH Oberon System Source License" contract available at: http://www.oberon.ethz.ch/ *)

MODULE QuotedPrintable IN Oberon; (* ejz,  *)
	IMPORT Files, Fonts, Strings, Texts, Oberon;

	VAR
		W: Texts.Writer;

	PROCEDURE HexVal(ch: CHAR): SIGNED32;
	BEGIN
		IF (ch >= "0") & (ch <= "9") THEN
			RETURN ORD(ch)-ORD("0")
		ELSIF (ch >= "A") & (ch <= "F") THEN
			RETURN ORD(ch)-ORD("A")+10
		ELSIF (ch >= "a") & (ch <= "f") THEN
			RETURN ORD(ch)-ORD("a")+10
		END
	END HexVal;

	PROCEDURE decodeText*(T: Texts.Text; beg: SIGNED32; F: Files.File; binary: BOOLEAN): BOOLEAN;
		VAR
			R: Texts.Reader;
			Ri: Files.Rider;
			ch, ch1, ch2: CHAR;
		PROCEDURE ReadWrite(c: CHAR);
		BEGIN
			Texts.Read(R, ch);
			IF ~R.eot & (R.lib IS Fonts.Font) THEN
				Files.Write(Ri, c)
			END
		END ReadWrite;
	BEGIN
		Files.Set(Ri, F, 0);
		Texts.OpenReader(R, T, beg);
		Texts.Read(R, ch);
		WHILE ~R.eot & (ch <= " ") & (R.lib IS Fonts.Font) DO
			Texts.Read(R, ch)
		END;
		WHILE ~R.eot & (R.lib IS Fonts.Font) DO
			IF ch = "=" THEN
				Texts.Read(R, ch1); Texts.Read(R, ch2);
				IF Strings.IsHexDigit(ch1) & Strings.IsHexDigit(ch2) THEN
					ch := CHR(HexVal(ch1)*16+HexVal(ch2));
					IF ~binary THEN
						ch := Strings.ISOToOberon[ORD(ch)]
					END;
					ReadWrite(ch)
				ELSIF ch1 = Strings.CR THEN
					ch := ch2
				ELSE
					Files.Write(Ri, "="); Files.Write(Ri, ch1);
					ReadWrite(ch2)
				END
			ELSE
				ReadWrite(ch)
			END
		END;
		RETURN TRUE
	END decodeText;

	PROCEDURE Decode(binary: BOOLEAN);
		VAR
			S: Texts.Scanner;
			F: Files.File;
			T: Texts.Text;
			beg, end, time: SIGNED32;
	BEGIN
		Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
		Texts.Scan(S);
		IF S.class IN {Texts.Name, Texts.String} THEN
			Texts.WriteString(W, S.s);
			F := Files.New(S.s);
			Texts.Scan(S);
			IF (S.class = Texts.Char) & ((S.c = "@") OR (S.c = "^")) THEN
				T := NIL;
				time := -1;
				Oberon.GetSelection(T, beg, end, time);
				IF T = NIL THEN
					RETURN
				END
			ELSIF S.class IN {Texts.Name, Texts.String} THEN
				NEW(T);
				Texts.Open(T, S.s);
				beg := 0
			ELSE
				beg := Texts.Pos(S);
				T := Oberon.Par.text
			END;
			IF decodeText(T, beg, F, binary) THEN
				Files.Register(F);
				Texts.WriteString(W, " done")
			ELSE
				Texts.WriteString(W, " failed")
			END;
			Texts.WriteLn(W);
			Texts.Append(Oberon.Log, W.buf)
		END
	END Decode;

	PROCEDURE DecodeText*;
	BEGIN
		Decode(FALSE)
	END DecodeText;

	PROCEDURE DecodeFile*;
	BEGIN
		Decode(TRUE)
	END DecodeFile;

BEGIN
	Texts.OpenWriter(W)
END QuotedPrintable.