kolibrios/programs/develop/cedit/SRC/Search.ob07
Anton Krotov 3ade12b666 CEdit: fixed whole word search
git-svn-id: svn://kolibrios.org@9907 a494cfbc-eb01-0410-851d-a64ba20cac60
2023-03-18 12:35:25 +00:00

176 lines
3.8 KiB
Plaintext

(*
Copyright 2021-2023 Anton Krotov
This file is part of CEdit.
CEdit 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.
CEdit 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 CEdit. If not, see <http://www.gnu.org/licenses/>.
*)
MODULE Search;
IMPORT
CB := Clipboard, List, Utils, SYSTEM;
CONST
itemSize = 64;
TYPE
tBuffer = CB.tBuffer;
tIdxTable = ARRAY 65536, 2 OF INTEGER;
tPos* = POINTER TO RECORD (List.tItem)
cnt*: INTEGER;
pos*: ARRAY itemSize OF INTEGER
END;
VAR
table: POINTER TO RECORD data: tIdxTable END;
PROCEDURE _index (text: tBuffer; cs: BOOLEAN; VAR table: tIdxTable): tBuffer;
VAR
pChar, cnt, i: INTEGER;
c: WCHAR;
res: tBuffer;
BEGIN
pChar := text.dataPtr;
cnt := CB.bufSize(text) DIV SYSTEM.SIZE(WCHAR);
FOR i := 0 TO 65535 DO
table[i, 1] := 0
END;
i := cnt;
WHILE i > 0 DO
SYSTEM.GET(pChar, c);
IF ~cs & Utils.lower(c) THEN
SYSTEM.PUT(pChar, c)
END;
INC(table[ORD(c), 1]);
INC(pChar, SYSTEM.SIZE(WCHAR));
DEC(i)
END;
res := CB.create(cnt*SYSTEM.SIZE(INTEGER));
table[0, 0] := res.dataPtr;
FOR i := 1 TO 65535 DO
table[i, 0] := table[i - 1, 0] + table[i - 1, 1]*SYSTEM.SIZE(INTEGER)
END;
pChar := text.dataPtr;
i := 0;
WHILE i < cnt DO
SYSTEM.GET(pChar, c);
SYSTEM.PUT(table[ORD(c), 0], i);
INC(table[ORD(c), 0], SYSTEM.SIZE(INTEGER));
INC(pChar, SYSTEM.SIZE(WCHAR));
INC(i)
END;
FOR i := 0 TO 65535 DO
DEC(table[i, 0], table[i, 1]*SYSTEM.SIZE(INTEGER))
END
RETURN res
END _index;
PROCEDURE index* (text: tBuffer; cs: BOOLEAN): tBuffer;
BEGIN
IF table = NIL THEN
NEW(table)
END
RETURN _index(text, cs, table.data)
END index;
PROCEDURE next* (VAR item: tPos; VAR i: INTEGER): INTEGER;
VAR
res: INTEGER;
BEGIN
IF (item # NIL) & (i >= item.cnt) THEN
item := item.next(tPos);
i := 0;
END;
IF (item # NIL ) & (i < item.cnt) THEN
res := item.pos[i];
INC(i)
ELSE
res := -1
END
RETURN res
END next;
PROCEDURE find* (text: tBuffer; s: ARRAY OF WCHAR; whole: BOOLEAN; list: List.tList; offset: INTEGER);
VAR
k, pos, n, i, x, prev_item_pos: INTEGER;
item: tPos;
c1, c2: WCHAR;
flag: BOOLEAN;
BEGIN
ASSERT(table # NIL);
n := LENGTH(s);
i := 0;
WHILE (i < n) & whole DO
whole := Utils.isWordChar(s[i]);
INC(i)
END;
k := table.data[ORD(s[0]), 1];
pos := table.data[ORD(s[0]), 0];
prev_item_pos := 0;
WHILE k > 0 DO
SYSTEM.GET(pos, x);
IF Utils.streq(text.dataPtr + x*SYSTEM.SIZE(WCHAR), SYSTEM.ADR(s[0]), n) THEN
flag := whole;
IF flag THEN
IF x > 0 THEN
SYSTEM.GET(text.dataPtr + (x - 1)*SYSTEM.SIZE(WCHAR), c1);
ELSE
c1 := 0X
END;
SYSTEM.GET(text.dataPtr + (x + n)*SYSTEM.SIZE(WCHAR), c2);
flag := Utils.isWordChar(c1) OR Utils.isWordChar(c2)
END;
IF ~flag & (x >= prev_item_pos) THEN
prev_item_pos := x + n;
item := list.last(tPos);
IF (item = NIL) OR (item.cnt = itemSize) THEN
NEW(item);
item.cnt := 0;
List.append(list, item)
END;
item.pos[item.cnt] := x + offset;
INC(item.cnt)
END
END;
INC(pos, SYSTEM.SIZE(INTEGER));
DEC(k)
END
END find;
PROCEDURE close*;
BEGIN
IF table # NIL THEN
DISPOSE(table)
END
END close;
BEGIN
table := NIL
END Search.