(* Copyright 2016-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 FB2READ; IMPORT DOM, SU := SysUtils, S := Strings, W := Window, Settings, OpenDlg, G := Graph, SelEnc, Ini, File, box_lib, Font, SearchForm, Toolbar; CONST CLOSE = 1; BACK = 16; FORWARD = 17; CONTENTS = 18; DESCR = 19; SETTINGS = 20; SEARCH = 21; KEY_DOWN = 80; KEY_UP = 72; KEY_PG_DOWN = 81; KEY_PG_UP = 73; KEY_HOME = 71; KEY_END = 79; KEY_F2 = 60; KEY_F3 = 61; KEY_F4 = 62; KEY_F10 = 68; TOOLBAR_LEFT = 5; TOOLBAR_TOP = 6; BUTTON_HEIGHT = 24; CANVAS_LEFT = 1; CANVAS_TOP = 2 * TOOLBAR_TOP + Toolbar.BtnSize; WINDOW_BEVEL = 4; SCROLLBAR_WIDTH = 20; STATUSBAR_HEIGHT = 18; VAR Window : W.tWindow; toolbar : Toolbar.tToolbar; SkinHeight : INTEGER; Open : OpenDlg.Dialog; FileName : S.STRING; sb : box_lib.scrollbar; PROCEDURE ToolbarEnable; BEGIN Toolbar.enable(toolbar, BACK, DOM.BackEnabled()); Toolbar.enable(toolbar, FORWARD, DOM.FrwEnabled()); Toolbar.enable(toolbar, CONTENTS, DOM.ContentsEnabled()); Toolbar.enable(toolbar, DESCR, DOM.DescrEnabled()); END ToolbarEnable; PROCEDURE ToolBar; BEGIN sb := box_lib.kolibri_scrollbar(sb, (G.Buffer.Width + CANVAS_LEFT) * 65536 + SCROLLBAR_WIDTH + 1, CANVAS_TOP * 65536 + G.Buffer.Height, SCROLLBAR_WIDTH, sb.max_area, sb.cur_area, sb.position, SU.lightColor, SU.btnColor, 0, 0); box_lib.scrollbar_v_draw(sb); ToolbarEnable; Toolbar.draw(toolbar); END ToolBar; PROCEDURE Resize; VAR Width, Height: INTEGER; BEGIN SU.GetWindowPos(Window.left, Window.top); SU.GetWindowSize(Width, Height); IF (Window.width # Width) OR (Window.height # Height) OR (SkinHeight # SU.SkinHeight()) THEN SU.MinMax(Width, 640, 65535); SU.MinMax(Height, 400, 65535); Window.dWidth := Width - Window.width; Window.dHeight := Height - Window.height; Window.width := Width; Window.height := Height; SU.SetWindowSize(Width, Height); DOM.Resize(G.Buffer.Width + Window.dWidth, G.Buffer.Height + Window.dHeight + (SkinHeight - SU.SkinHeight())); SkinHeight := SU.SkinHeight() END END Resize; PROCEDURE DrawStatus; BEGIN SU.DrawRect(0, Window.height - SkinHeight - WINDOW_BEVEL - STATUSBAR_HEIGHT + 1, Window.width - 2 * WINDOW_BEVEL - 1, STATUSBAR_HEIGHT, SU.winColor); IF DOM.urlstr # "" THEN SU.OutText(CANVAS_LEFT, Window.height - SkinHeight - WINDOW_BEVEL - STATUSBAR_HEIGHT + 2, DOM.urlstr, MIN(LENGTH(DOM.urlstr), (Window.width - 2 * WINDOW_BEVEL - 1 - CANVAS_LEFT * 2) DIV 8), SU.textColor) ELSIF DOM.found() THEN SU.OutText(CANVAS_LEFT, Window.height - SkinHeight - WINDOW_BEVEL - STATUSBAR_HEIGHT + 2, "F2 - first | F3 - next | F4 - prev. | F10 - exit", 48, SU.textColor) END END DrawStatus; PROCEDURE DrawWindow; BEGIN SU.GetSystemColors; SU.WindowRedrawStatus(1); IF Window.created THEN IF ~SU.RolledUp() THEN Resize; DOM.SetWinSize(Window.width, Window.height) END ELSE Window.created := TRUE END; SU.DefineAndDrawWindow(Window.left, Window.top, Window.width, Window.height, SU.winColor, LSL(ORD({0, 1, 2}), 4) + 4 - ORD(DOM.loaded), Window.caption); IF ~SU.RolledUp() THEN SU.DrawRect(0, 0, Window.width - 2 * WINDOW_BEVEL - 1, CANVAS_TOP, SU.winColor); SU.DrawRect(0, Window.height - SkinHeight - WINDOW_BEVEL - STATUSBAR_HEIGHT + 1, Window.width - 2 * WINDOW_BEVEL - 1, STATUSBAR_HEIGHT, SU.winColor); SU.DrawRect(0, 0, CANVAS_LEFT, Window.height - SkinHeight - WINDOW_BEVEL, SU.winColor); SU.DrawRect(Window.width - 2 * WINDOW_BEVEL - CANVAS_LEFT - 1 - SCROLLBAR_WIDTH - 2, 0, CANVAS_LEFT + SCROLLBAR_WIDTH + 2, Window.height - SkinHeight - WINDOW_BEVEL, SU.winColor); IF DOM.loaded THEN ToolBar; DOM.Draw; DrawStatus END END; SU.WindowRedrawStatus(2) END DrawWindow; PROCEDURE ConvMousePos(VAR X, Y: INTEGER); BEGIN X := X - Window.left - WINDOW_BEVEL - 1; Y := Y - Window.top - SkinHeight END ConvMousePos; PROCEDURE DrawToolbar; BEGIN ToolbarEnable; Toolbar.drawIcons(toolbar) END DrawToolbar; PROCEDURE ButtonClick; BEGIN CASE SU.GetButtonCode() OF |0 : |CLOSE : SearchForm.close(FALSE); Settings.Close; DOM.Close |BACK : DOM.Back |FORWARD : DOM.Forward |CONTENTS : DOM.Contents |DESCR : DOM.Descr |SEARCH : DOM.OpenSearch |SETTINGS : Settings.Open END; DOM.Draw; DrawStatus END ButtonClick; PROCEDURE KeyDown; VAR key: INTEGER; shift, ctrl: BOOLEAN; BEGIN SU.getKBState(shift, ctrl); key := SU.GetKey() DIV 65536; CASE key OF |KEY_DOWN : DOM.Scroll(1) |KEY_UP : DOM.Scroll(-1) |KEY_PG_DOWN : DOM.PageDown |KEY_PG_UP : DOM.PageUp |KEY_HOME : DOM.Home |KEY_END : DOM.End |KEY_F2 : DOM.Find(0) |KEY_F3 : DOM.Find(1) |KEY_F4 : DOM.Find(-1) |KEY_F10 : DOM.CloseSearch |33 : IF ctrl THEN DOM.OpenSearch END (* ctrl-F *) ELSE END; DOM.Draw; DrawStatus END KeyDown; PROCEDURE CanvasIsClicked(X, Y: INTEGER): BOOLEAN; RETURN (CANVAS_LEFT <= X) & (X < CANVAS_LEFT + G.Buffer.Width) & (CANVAS_TOP <= Y) & (Y < CANVAS_TOP + G.Buffer.Height) END CanvasIsClicked; PROCEDURE MouseEvent; VAR mouse_status : SET; X, Y : INTEGER; scroll : INTEGER; BEGIN SU.MousePos(X, Y); mouse_status := SU.MouseStatus(); scroll := SU.MouseVScroll(); IF SU.L_BUTTON IN mouse_status THEN ConvMousePos(X, Y); IF CanvasIsClicked(X, Y) THEN X := X - CANVAS_LEFT; Y := Y - CANVAS_TOP; DOM.Click(X, Y, TRUE) END ELSIF scroll # 0 THEN DOM.Scroll(scroll*2); DOM.Draw ELSE ConvMousePos(X, Y); IF CanvasIsClicked(X, Y) THEN X := X - CANVAS_LEFT; Y := Y - CANVAS_TOP; DOM.Click(X, Y, FALSE) END END END MouseEvent; PROCEDURE Empty; END Empty; PROCEDURE OpenFile; BEGIN Open := OpenDlg.Create(Empty, 0, Ini.Default, Ini.Files); OpenDlg.Show(Open, 500, 400); WHILE Open.status = 2 DO SU.Pause(30) END; IF Open.status = 0 THEN SU.Halt END; COPY(Open.FilePath, FileName); OpenDlg.Destroy(Open) END OpenFile; PROCEDURE IsFB2(FileName: S.STRING): BOOLEAN; VAR temp: S.STRING; BEGIN temp := FileName; S.Reverse(temp); temp[4] := 0X; S.UCase(temp) RETURN temp = "2BF." END IsFB2; PROCEDURE main(title: ARRAY OF CHAR); VAR WinW, X1, Y1, X2, Y2, scr_pos, ignore: INTEGER; Win2: W.tWindow; resize: BOOLEAN; FilePath: S.STRING; defpath: BOOLEAN; BEGIN SkinHeight := SU.SkinHeight(); sb := box_lib.kolibri_new_scrollbar(10 * 65536 + 200, 10 * 65536 + 30, 25, 15, 10, 0, 0, 0, 0, 0); DOM.SetScrollBar(sb); defpath := TRUE; SU.GetParam(FileName); IF FileName = "" THEN OpenFile END; IF FileName[0] = "!" THEN FileName[0] := "/"; defpath := FALSE END; IF defpath THEN FilePath := FileName; S.GetPath(FilePath); Ini.SetDefaultPath(FilePath); DOM.SetColors; DOM.Set_b_pict(Ini.b_pict); Ini.Save(DOM.Settings.Colors, DOM.Settings.b_pict) END; IF ~IsFB2(FileName) THEN SelEnc.Show(FileName) END; SU.SetEventsMask({0, 1, 2, 5, 31}); SU.GetScreenArea(X1, Y1, X2, Y2); WinW := (X2 - X1) DIV 2; SU.MinMax(WinW, 640, 65535); W.init(Window, (X2 - X1 - WinW) DIV 2, Y1, WinW, Y2 - Y1, title); Settings.Default; DOM.GetWinSize(FileName, Window.width, Window.height); Win2 := Window; resize := FALSE; IF Win2.width > X2 - X1 THEN Win2.width := X2 - X1; resize := TRUE END; IF Win2.height > Y2 - Y1 THEN Win2.height := Y2 - Y1; resize := TRUE END; DOM.Init(CANVAS_LEFT, CANVAS_TOP, Window.width - 2 * CANVAS_LEFT - 2 * WINDOW_BEVEL - 1 - SCROLLBAR_WIDTH - 2, Window.height - SkinHeight - CANVAS_TOP - WINDOW_BEVEL - STATUSBAR_HEIGHT + 1); DOM.SetColors; DOM.Set_b_pict(Ini.b_pict); Window := Win2; G.InitSize(Window.width - 2 * CANVAS_LEFT - 2 * WINDOW_BEVEL - 1 - SCROLLBAR_WIDTH, Window.height - SkinHeight - CANVAS_TOP - WINDOW_BEVEL + 1 - STATUSBAR_HEIGHT); S.Append(Window.caption, " - "); S.Append(Window.caption, FileName); Toolbar.create(toolbar, TOOLBAR_LEFT, TOOLBAR_TOP); Toolbar.add(toolbar, BACK, 30, ""); Toolbar.add(toolbar, FORWARD, 31, ""); Toolbar.delimiter(toolbar); Toolbar.add(toolbar, CONTENTS, 3, ""); Toolbar.delimiter(toolbar); Toolbar.add(toolbar, SEARCH, 49, ""); Toolbar.delimiter(toolbar); Toolbar.add(toolbar, DESCR, 66, ""); Toolbar.delimiter(toolbar); Toolbar.add(toolbar, SETTINGS, 60, ""); DOM.Open(FileName, DrawWindow, DrawStatus, DrawToolbar); IF resize THEN DOM.Resize(Window.width - 2 * CANVAS_LEFT - 2 * WINDOW_BEVEL - 1 - SCROLLBAR_WIDTH, Window.height - SkinHeight - CANVAS_TOP - WINDOW_BEVEL + 1 - STATUSBAR_HEIGHT) END; DrawWindow; scr_pos := sb.position; WHILE TRUE DO CASE SU.WaitForEvent() OF |1 : DrawWindow |2 : IF ~SU.RolledUp() THEN KeyDown ELSE ignore := SU.GetKey() END |3 : ButtonClick |6 : IF ~SU.RolledUp() THEN box_lib.scrollbar_v_mouse(sb); IF sb.position # scr_pos THEN DOM.ScrollBar; DOM.Draw; scr_pos := sb.position; END; MouseEvent ELSE ignore := SU.MouseVScroll() END END END END main; BEGIN main("FB2 Reader v0.97c") END FB2READ.