kolibrios-fun/programs/other/fb2reader/SRC/tables.ob07
Anton Krotov 4c20c082c1 FB2 Reader: upload source, small changes
git-svn-id: svn://kolibrios.org@9896 a494cfbc-eb01-0410-851d-a64ba20cac60
2023-01-22 14:20:23 +00:00

257 lines
6.0 KiB
Plaintext

(*
Copyright 2016 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 <http://www.gnu.org/licenses/>.
*)
MODULE tables;
IMPORT V := Vector;
TYPE
Int = POINTER TO RECORD (V.ANYREC) value: INTEGER END;
Cell = POINTER TO RECORD (V.ANYREC) top, bottom, left, right, colspan, rowspan: INTEGER END;
Tab = POINTER TO RECORD (V.ANYREC) col, row: INTEGER END;
Table* = POINTER TO RECORD
tab : V.VECTOR;
h_lines : V.VECTOR;
v_lines : V.VECTOR;
cells* : V.VECTOR;
tab_x, tab_y, max_length: INTEGER
END;
PROCEDURE GetCell (t: Table; cell: INTEGER): Cell;
VAR any: V.ANYPTR;
BEGIN
any := V.get(t.cells, cell)
RETURN any(Cell)
END GetCell;
PROCEDURE GetInt (v: V.VECTOR; idx: INTEGER): INTEGER;
VAR any: V.ANYPTR;
BEGIN
any := V.get(v, idx)
RETURN any(Int).value
END GetInt;
PROCEDURE PutInt (v: V.VECTOR; idx, value: INTEGER);
VAR any: V.ANYPTR;
BEGIN
any := V.get(v, idx);
any(Int).value := value
END PutInt;
PROCEDURE PushInt (v: V.VECTOR; value: INTEGER);
VAR int: Int;
BEGIN
NEW(int);
int.value := value;
V.push(v, int)
END PushInt;
PROCEDURE get_tab_xy (t: Table; x, y: INTEGER): BOOLEAN;
VAR i: INTEGER;
tab: Tab; any: V.ANYPTR;
res: BOOLEAN;
BEGIN
res := FALSE;
i := 0;
WHILE (i < t.tab.count) & ~res DO
any := V.get(t.tab, i);
tab := any(Tab);
res := (tab.col = x) & (tab.row = y);
INC(i)
END
RETURN res
END get_tab_xy;
PROCEDURE set_tab_xy (t: Table; x, y: INTEGER);
VAR tab: Tab;
BEGIN
NEW(tab);
tab.col := x;
tab.row := y;
V.push(t.tab, tab)
END set_tab_xy;
PROCEDURE tr* (t: Table);
BEGIN
INC(t.tab_y);
WHILE t.h_lines.count < t.tab_y + 10 DO
PushInt(t.h_lines, 0)
END;
t.tab_x := 0;
WHILE get_tab_xy(t, t.tab_x, t.tab_y) DO
INC(t.tab_x);
WHILE t.v_lines.count < t.tab_x + 10 DO
PushInt(t.v_lines, 0)
END
END
END tr;
PROCEDURE td* (t: Table; colspan, rowspan: INTEGER);
VAR i, j: INTEGER; _cell: Cell;
BEGIN
FOR i := t.tab_x TO t.tab_x + colspan - 1 DO
FOR j := t.tab_y TO t.tab_y + rowspan - 1 DO
set_tab_xy(t, i, j);
IF i > t.max_length THEN
t.max_length := i
END
END
END;
NEW(_cell);
_cell.left := t.tab_x;
_cell.top := t.tab_y;
_cell.right := t.tab_x + colspan;
WHILE t.v_lines.count < _cell.right + 10 DO
PushInt(t.v_lines, 0)
END;
_cell.bottom := t.tab_y + rowspan;
WHILE t.h_lines.count < _cell.bottom + 10 DO
PushInt(t.h_lines, 0)
END;
_cell.colspan := colspan;
_cell.rowspan := rowspan;
V.push(t.cells, _cell);
WHILE get_tab_xy(t, t.tab_x, t.tab_y) DO
INC(t.tab_x);
WHILE t.v_lines.count < t.tab_x + 10 DO
PushInt(t.v_lines, 0)
END
END
END td;
PROCEDURE set_width* (t: Table; cell, width: INTEGER);
VAR left, right, old_width, d_width, i: INTEGER; _cell: Cell;
BEGIN
_cell := GetCell(t, cell);
right := GetInt(t.v_lines, _cell.right);
left := GetInt(t.v_lines, _cell.left);
old_width := right - left;
d_width := width - old_width;
PutInt(t.v_lines, _cell.right, left + width);
FOR i := _cell.right + 1 TO t.v_lines.count - 1 DO
PutInt(t.v_lines, i, GetInt(t.v_lines, i) + d_width)
END
END set_width;
PROCEDURE set_height* (t: Table; cell, height: INTEGER);
VAR top, bottom, old_height, d_height, i: INTEGER; _cell: Cell;
BEGIN
_cell := GetCell(t, cell);
top := GetInt(t.h_lines, _cell.top);
bottom := GetInt(t.h_lines, _cell.bottom);
old_height := bottom - top;
d_height := height - old_height;
PutInt(t.h_lines, _cell.bottom, top + height);
FOR i := _cell.bottom + 1 TO t.h_lines.count - 1 DO
PutInt(t.h_lines, i, GetInt(t.h_lines, i) + d_height)
END
END set_height;
PROCEDURE get_height* (t: Table; cell: INTEGER): INTEGER;
VAR _cell: Cell;
BEGIN
_cell := GetCell(t, cell)
RETURN GetInt(t.h_lines, _cell.bottom) - GetInt(t.h_lines, _cell.top)
END get_height;
PROCEDURE get_width* (t: Table; cell: INTEGER): INTEGER;
VAR _cell: Cell;
BEGIN
_cell := GetCell(t, cell)
RETURN GetInt(t.v_lines, _cell.right) - GetInt(t.v_lines, _cell.left)
END get_width;
PROCEDURE get_x* (t: Table; cell: INTEGER): INTEGER;
VAR _cell: Cell;
BEGIN
_cell := GetCell(t, cell)
RETURN GetInt(t.v_lines, _cell.left)
END get_x;
PROCEDURE get_y* (t: Table; cell: INTEGER): INTEGER;
VAR _cell: Cell;
BEGIN
_cell := GetCell(t, cell)
RETURN GetInt(t.h_lines, _cell.top)
END get_y;
PROCEDURE get_table_height* (t: Table): INTEGER;
RETURN GetInt(t.h_lines, t.tab_y + 1)
END get_table_height;
PROCEDURE table* (t: Table; tab_width: INTEGER; open: BOOLEAN);
VAR i, width: INTEGER; _cell: Cell;
BEGIN
IF open THEN
t.cells := V.create(1024);
t.v_lines := V.create(1024);
t.h_lines := V.create(1024);
t.tab := V.create(1024);
t.tab_x := 0;
t.tab_y := -1;
t.max_length := 0;
ELSE
width := tab_width DIV (t.max_length + 1);
FOR i := 0 TO t.cells.count - 1 DO
_cell := GetCell(t, i);
set_width(t, i, width * _cell.colspan)
END
END
END table;
PROCEDURE destroy* (t: Table);
BEGIN
IF t # NIL THEN
V.destroy(t.tab, NIL);
V.destroy(t.h_lines, NIL);
V.destroy(t.v_lines, NIL);
V.destroy(t.cells, NIL);
DISPOSE(t)
END
END destroy;
END tables.