(* Copyright 2016, 2018, 2020-2023 Anton Krotov This file is part of fb2read. fb2read is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. fb2read is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with fb2read. If not, see . *) MODULE SelEnc; IMPORT SU := SysUtils, W := Window, S := Strings, SYSTEM, K := KOSAPI, File; CONST AUTO = 15; CP866 = 16; CP1251 = 17; CP1252 = 18; CP1250 = 19; UTF8 = 20; BtnH = 30; BtnW = 150; BtnX = 5; BtnY = 10; BtnInter = 10; tempfile* = "/tmp0/1/~temp.fb2"; VAR Window: W.tWindow; pos, mem, mem2, pos2: INTEGER; PROCEDURE Buttons; VAR Y : INTEGER; BEGIN Y := BtnY; SU.CreateButton(AUTO, BtnX, Y, BtnW, BtnH, SU.btnColor, "AUTO" ); INC(Y, BtnH + BtnInter); SU.CreateButton(CP866, BtnX, Y, BtnW, BtnH, SU.btnColor, "CP-866" ); INC(Y, BtnH + BtnInter); SU.CreateButton(CP1251, BtnX, Y, BtnW, BtnH, SU.btnColor, "CP-1251"); INC(Y, BtnH + BtnInter); SU.CreateButton(CP1252, BtnX, Y, BtnW, BtnH, SU.btnColor, "CP-1252"); INC(Y, BtnH + BtnInter); SU.CreateButton(CP1250, BtnX, Y, BtnW, BtnH, SU.btnColor, "CP-1250"); INC(Y, BtnH + BtnInter); SU.CreateButton(UTF8, BtnX, Y, BtnW, BtnH, SU.btnColor, "UTF-8" ) END Buttons; PROCEDURE DrawWindow; BEGIN SU.GetSystemColors; SU.WindowRedrawStatus(1); SU.DefineAndDrawWindow(Window.left, Window.top, Window.width, Window.height, SU.winColor, LSL(ORD({0, 1}), 4) + 4, Window.caption); Buttons; SU.WindowRedrawStatus(2) END DrawWindow; PROCEDURE getch (): CHAR; VAR ch: CHAR; BEGIN SYSTEM.GET(mem + pos, ch); INC(pos) RETURN ch END getch; PROCEDURE WriteStr (s: ARRAY OF CHAR); BEGIN SYSTEM.MOVE(SYSTEM.ADR(s[0]), mem2 + pos2, LENGTH(s)); pos2 := pos2 + LENGTH(s) END WriteStr; PROCEDURE WriteChar (ch: CHAR); BEGIN SYSTEM.PUT(mem2 + pos2, ch); INC(pos2) END WriteChar; PROCEDURE convert (ibuf, size: INTEGER; out: S.STRING; encoding: INTEGER); CONST buf_size = 1024*16; VAR F: File.FS; n: INTEGER; CR: BOOLEAN; ch: CHAR; buffer: ARRAY buf_size OF BYTE; BEGIN mem := ibuf; pos := 0; F := File.Create(out); mem2 := SYSTEM.ADR(buffer[0]); pos2 := 0; WriteStr('' + 0DX + 0AX + ""); WHILE pos < size DO IF pos2 > buf_size - 32 THEN n := File.Write(F, mem2, pos2); pos2 := 0 END; ch := getch(); CASE ch OF |"<": WriteStr("<") |">": WriteStr(">") |"&": WriteStr("&") |"'": WriteStr("'") |'"': WriteStr(""") |0DX: WriteStr("") |0AX: IF ~CR THEN WriteStr("") END | 0X: WriteChar(20X) ELSE WriteChar(ch) END; CR := ch = 0DX END; WriteStr(""); n := File.Write(F, mem2, pos2); File.Close(F) END convert; PROCEDURE auto (ptr, size: INTEGER): INTEGER; VAR enc: INTEGER; PROCEDURE SearchPair (ptr, size: INTEGER; chr1, chr2: BYTE): BOOLEAN; VAR c, c0: BYTE; res: BOOLEAN; BEGIN c := 0; res := FALSE; WHILE (size > 0) & ~res DO c0 := c; SYSTEM.GET(ptr, c); IF (c = chr2) & (c0 = chr1) THEN res := TRUE END; INC(ptr); DEC(size) END RETURN res END SearchPair; BEGIN IF SearchPair(ptr, size, 208, 190) THEN enc := UTF8 ELSE IF SearchPair(ptr, size, 239, 240) OR SearchPair(ptr, size, 241, 242) THEN enc := CP1251 ELSE enc := CP866 END END RETURN enc END auto; PROCEDURE ButtonClick (fname: S.STRING); VAR encoding: INTEGER; program, file: S.STRING; data, size: INTEGER; BEGIN data := File.Load(fname, size); SU.ErrorIf(data = 0, 1); encoding := SU.GetButtonCode(); IF encoding = AUTO THEN encoding := auto(data, size) END; convert(data, size, tempfile, encoding); S.PtrToString(K.GetName(), program); file := tempfile; file[0] := "!"; SU.Run(program, SYSTEM.ADR(file)); SU.Halt END ButtonClick; PROCEDURE Show* (fname: S.STRING); VAR X1, Y1, X2, Y2: INTEGER; BEGIN SU.SetEventsMask({0, 2, 31}); SU.GetScreenArea(X1, Y1, X2, Y2); W.init(Window, 0, 0, BtnX * 2 + BtnW + 10, (BtnH + BtnInter) * 6 + BtnY * 2 + SU.SkinHeight() - 5, "Encoding"); Window.left := (X2 - X1 - Window.width) DIV 2; Window.top := (Y2 - Y1 - Window.height) DIV 2; DrawWindow; WHILE TRUE DO CASE SU.WaitForEvent() OF |1: DrawWindow |3: ButtonClick(fname) END END END Show; END SelEnc.