forked from KolibriOS/kolibrios
9398cd7961
- added line spacing setting - disabled highlighting of anonymous labels git-svn-id: svn://kolibrios.org@9946 a494cfbc-eb01-0410-851d-a64ba20cac60
3033 lines
79 KiB
Plaintext
3033 lines
79 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 Text;
|
|
|
|
IMPORT
|
|
List, Lines,
|
|
G := Graph,
|
|
U := Utils,
|
|
RW, Search,
|
|
E := Encodings,
|
|
CB := Clipboard,
|
|
ChangeLog, File,
|
|
Lang := Languages;
|
|
|
|
|
|
CONST
|
|
|
|
SPACE = Lines.SPACE;
|
|
TAB = Lines.TAB;
|
|
TAB1 = Lines.TAB1;
|
|
lenEOL = CB.lenEOL;
|
|
|
|
mark_width = 2;
|
|
pad_left = mark_width + 3;
|
|
pad_top = 1;
|
|
MaxLineSpacing* = 8;
|
|
|
|
|
|
TYPE
|
|
|
|
tPoint* = RECORD
|
|
X*, Y*: INTEGER
|
|
END;
|
|
|
|
pPoint = POINTER TO tPoint;
|
|
|
|
tString* = ARRAY 1000 OF WCHAR;
|
|
|
|
tLine = Lines.tLine;
|
|
|
|
tGuard = POINTER TO RECORD (ChangeLog.tGuard)
|
|
selected: BOOLEAN;
|
|
cursor, select2, scroll: tPoint;
|
|
CurX: INTEGER
|
|
END;
|
|
|
|
tText* = POINTER TO RECORD (List.tList)
|
|
cursor, select, select2: pPoint;
|
|
scroll: tPoint;
|
|
CurX: INTEGER;
|
|
smallChange: INTEGER;
|
|
modified*, smallMove,
|
|
comments, guard, fasm*,
|
|
search, cs, whole, wordSel: BOOLEAN;
|
|
edition*: tGuard;
|
|
curLine: tLine;
|
|
lang*: INTEGER;
|
|
enc, eol: INTEGER;
|
|
foundList: List.tList;
|
|
foundSel*, foundCur*, foundCnt*: INTEGER;
|
|
searchText: tString;
|
|
LinesVector: Lines.tVector;
|
|
chLog*: ChangeLog.tLog;
|
|
maxLength*: INTEGER;
|
|
fileName*: RW.tFileName
|
|
END;
|
|
|
|
tProcedure = PROCEDURE;
|
|
|
|
|
|
VAR
|
|
|
|
pdelete: PROCEDURE (text: tText);
|
|
ShowCursor: PROCEDURE;
|
|
|
|
colors: RECORD
|
|
text, back, seltext, selback, modified, saved, curline, numtext, numback: INTEGER;
|
|
comment, string, escape, num, delim, key1, key2, key3: INTEGER
|
|
END;
|
|
canvas: G.tCanvas;
|
|
drawCursor: BOOLEAN;
|
|
padding: RECORD left, top: INTEGER END;
|
|
size, textsize: tPoint;
|
|
charWidth, charHeight, LineSpacing*: INTEGER;
|
|
autoIndents*, lineNumbers*, autoBrackets*, trimSpace*: BOOLEAN;
|
|
|
|
|
|
PROCEDURE setLang* (text: tText; lang: INTEGER);
|
|
BEGIN
|
|
IF text.lang # lang THEN
|
|
text.fasm := lang = Lang.langFasm;
|
|
text.lang := lang
|
|
END;
|
|
text.comments := TRUE;
|
|
Lang.setCurLang(text.lang)
|
|
END setLang;
|
|
|
|
|
|
PROCEDURE setName* (text: tText; name: RW.tFileName);
|
|
VAR
|
|
ext: RW.tFileName;
|
|
BEGIN
|
|
text.fileName := name;
|
|
U.getFileName(name, ext, ".");
|
|
U.lowcase8(ext);
|
|
setLang(text, Lang.getLang(ext))
|
|
END setName;
|
|
|
|
|
|
PROCEDURE getPos* (text: tText; VAR x, y: INTEGER);
|
|
BEGIN
|
|
x := text.cursor.X + 1;
|
|
y := text.cursor.Y + 1
|
|
END getPos;
|
|
|
|
|
|
PROCEDURE getScroll* (text: tText; VAR x, y: INTEGER);
|
|
BEGIN
|
|
x := text.scroll.X;
|
|
y := text.scroll.Y
|
|
END getScroll;
|
|
|
|
|
|
PROCEDURE getTextSize* (VAR x, y: INTEGER);
|
|
BEGIN
|
|
x := textsize.X;
|
|
y := textsize.Y
|
|
END getTextSize;
|
|
|
|
|
|
PROCEDURE getTextRect* (VAR left, top, rigth, bottom: INTEGER);
|
|
BEGIN
|
|
left := padding.left - 1;
|
|
top := padding.top - 1;
|
|
rigth := size.X - 1;
|
|
bottom := top + size.Y - 1;
|
|
END getTextRect;
|
|
|
|
|
|
PROCEDURE toggleNumbers*;
|
|
BEGIN
|
|
lineNumbers := ~lineNumbers
|
|
END toggleNumbers;
|
|
|
|
|
|
PROCEDURE toggleIndents*;
|
|
BEGIN
|
|
autoIndents := ~autoIndents
|
|
END toggleIndents;
|
|
|
|
|
|
PROCEDURE toggleBrackets*;
|
|
BEGIN
|
|
autoBrackets := ~autoBrackets
|
|
END toggleBrackets;
|
|
|
|
|
|
PROCEDURE toggleTrimSpace*;
|
|
BEGIN
|
|
trimSpace := ~trimSpace
|
|
END toggleTrimSpace;
|
|
|
|
|
|
PROCEDURE showCursor*;
|
|
BEGIN
|
|
drawCursor := TRUE
|
|
END showCursor;
|
|
|
|
|
|
PROCEDURE hideCursor*;
|
|
BEGIN
|
|
drawCursor := FALSE
|
|
END hideCursor;
|
|
|
|
|
|
PROCEDURE getString (src: tLine; pos, cnt: INTEGER; VAR dst: ARRAY OF WCHAR): INTEGER;
|
|
VAR
|
|
i: INTEGER;
|
|
BEGIN
|
|
i := 0;
|
|
WHILE (pos < src.length) & (cnt > 0) DO
|
|
IF i < LEN(dst) - 1 THEN
|
|
dst[i] := Lines.getChar(src, pos);
|
|
INC(i)
|
|
END;
|
|
INC(pos);
|
|
DEC(cnt)
|
|
END;
|
|
dst[i] := 0X
|
|
RETURN i
|
|
END getString;
|
|
|
|
|
|
PROCEDURE NextLine (VAR line: tLine);
|
|
BEGIN
|
|
line := line.next(tLine)
|
|
END NextLine;
|
|
|
|
|
|
PROCEDURE PrevLine (VAR line: tLine);
|
|
BEGIN
|
|
line := line.prev(tLine)
|
|
END PrevLine;
|
|
|
|
|
|
PROCEDURE SetColor (textColor, backColor: INTEGER);
|
|
BEGIN
|
|
G.SetTextColor(canvas, textColor);
|
|
G.SetBkColor(canvas, backColor)
|
|
END SetColor;
|
|
|
|
|
|
PROCEDURE ProcessComments (line: tLine; VAR depth, pos: INTEGER; minDepth, n: INTEGER; lang: INTEGER);
|
|
VAR
|
|
cond: INTEGER;
|
|
BEGIN
|
|
cond := 0;
|
|
WHILE (pos <= n) & (depth > minDepth) DO
|
|
Lang.comments(line, depth, cond, pos, n, lang);
|
|
INC(pos)
|
|
END;
|
|
DEC(pos)
|
|
END ProcessComments;
|
|
|
|
|
|
PROCEDURE getLine2 (text: tText; n: INTEGER): tLine;
|
|
VAR
|
|
item: tLine;
|
|
BEGIN
|
|
IF (0 <= n) & (n < text.count) THEN
|
|
item := Lines.getVectorItem(text.LinesVector, n)
|
|
ELSE
|
|
item := NIL
|
|
END
|
|
RETURN item
|
|
END getLine2;
|
|
|
|
|
|
PROCEDURE Comments (text: tText);
|
|
VAR
|
|
line: tLine;
|
|
i, k, cout: INTEGER;
|
|
BEGIN
|
|
IF text.smallChange = 1 THEN
|
|
line := getLine2(text, text.cursor.Y);
|
|
IF line.prev # NIL THEN
|
|
line.cin := line.prev(tLine).cout
|
|
ELSE
|
|
line.cin := 0
|
|
END;
|
|
cout := line.cout;
|
|
line.cout := line.cin;
|
|
i := 0;
|
|
ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
|
|
IF line.cout # cout THEN
|
|
text.smallChange := 0;
|
|
Comments(text)
|
|
END
|
|
ELSE
|
|
Lines.destroyVector(text.LinesVector);
|
|
text.LinesVector := Lines.createVector(text.count);
|
|
k := 0;
|
|
line := text.first(tLine);
|
|
Lines.setVectorItem(text.LinesVector, k, line);
|
|
INC(k);
|
|
line.cin := 0;
|
|
line.cout := 0;
|
|
i := 0;
|
|
ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
|
|
NextLine(line);
|
|
WHILE line # NIL DO
|
|
Lines.setVectorItem(text.LinesVector, k, line);
|
|
INC(k);
|
|
line.cin := line.prev(tLine).cout;
|
|
line.cout := line.cin;
|
|
i := 0;
|
|
ProcessComments(line, line.cout, i, -1, line.length - 1, text.lang);
|
|
NextLine(line)
|
|
END
|
|
END;
|
|
text.smallChange := 0;
|
|
text.comments := FALSE
|
|
END Comments;
|
|
|
|
|
|
PROCEDURE leadingSpaces (line: tLine): INTEGER;
|
|
VAR
|
|
i: INTEGER;
|
|
BEGIN
|
|
i := 0;
|
|
WHILE Lines.isSpace(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END
|
|
RETURN i
|
|
END leadingSpaces;
|
|
|
|
|
|
PROCEDURE parse (text: tText; line: tLine; y: INTEGER; backColor: INTEGER; lang: INTEGER);
|
|
VAR
|
|
c: WCHAR;
|
|
i, n, k: INTEGER;
|
|
cond, depth: INTEGER;
|
|
color: INTEGER;
|
|
hex: BOOLEAN;
|
|
isDgt: PROCEDURE (c: WCHAR): BOOLEAN;
|
|
|
|
|
|
PROCEDURE PrintLex (text: tText; line: tLine; lexStart, lexEnd: INTEGER; y: INTEGER; color, backColor: INTEGER);
|
|
VAR
|
|
lexLen: INTEGER;
|
|
BEGIN
|
|
SetColor(color, backColor);
|
|
lexLen := MAX(MIN(line.length - lexStart, lexEnd - lexStart + 1), 0);
|
|
G.TextOut(canvas, padding.left + (lexStart - text.scroll.X) * charWidth, y, Lines.getPChar(line, lexStart), lexLen, color)
|
|
END PrintLex;
|
|
|
|
|
|
PROCEDURE PrintComment (text: tText; line: tLine; VAR depth, i: INTEGER; w, y: INTEGER; backColor: INTEGER);
|
|
VAR
|
|
lexStart: INTEGER;
|
|
color: INTEGER;
|
|
BEGIN
|
|
IF (text.lang = Lang.langLua) & ~ODD(depth) THEN
|
|
color := colors.string
|
|
ELSIF (text.lang = Lang.langIni) & (depth = 1) THEN
|
|
color := colors.key2
|
|
ELSIF (text.lang = Lang.langPascal) & (depth = 3) THEN
|
|
color := colors.key3
|
|
ELSE
|
|
color := colors.comment
|
|
END;
|
|
lexStart := MAX(i - w, 0);
|
|
ProcessComments(line, depth, i, 0, line.length - 1, text.lang);
|
|
PrintLex(text, line, lexStart, i, y, color, backColor)
|
|
END PrintComment;
|
|
|
|
|
|
PROCEDURE upper (c: WCHAR): WCHAR;
|
|
BEGIN
|
|
IF U.upper(c) THEN END
|
|
RETURN c
|
|
END upper;
|
|
|
|
|
|
PROCEDURE UL (c: WCHAR): BOOLEAN;
|
|
RETURN (upper(c) = "U") OR (upper(c) = "L")
|
|
END UL;
|
|
|
|
|
|
PROCEDURE FL (c: WCHAR): BOOLEAN;
|
|
RETURN (upper(c) = "F") OR (upper(c) = "L")
|
|
END FL;
|
|
|
|
|
|
PROCEDURE ident (text: tText; VAR i: INTEGER; first, y: INTEGER; line: tLine; backColor: INTEGER; cs: BOOLEAN);
|
|
VAR
|
|
c: WCHAR;
|
|
lexLen: INTEGER;
|
|
s: ARRAY 32 OF WCHAR;
|
|
color: INTEGER;
|
|
BEGIN
|
|
c := Lines.getChar(line, i);
|
|
WHILE U.isLetter(c) OR (c = "_") OR U.isDigit(c) DO
|
|
INC(i);
|
|
c := Lines.getChar(line, i);
|
|
END;
|
|
DEC(i);
|
|
lexLen := getString(line, first, i - first + 1, s);
|
|
IF ~cs THEN
|
|
U.lowcase(s)
|
|
END;
|
|
IF Lang.isKey(s, text.lang, 1) THEN
|
|
color := colors.key1
|
|
ELSIF Lang.isKey(s, text.lang, 2) THEN
|
|
color := colors.key2
|
|
ELSIF Lang.isKey(s, text.lang, 3) THEN
|
|
color := colors.key3
|
|
ELSE
|
|
color := colors.text
|
|
END;
|
|
IF color # colors.text THEN
|
|
PrintLex(text, line, first, i, y, color, backColor)
|
|
END
|
|
END ident;
|
|
|
|
|
|
PROCEDURE String (text: tText; line: tLine; VAR i: INTEGER; y: INTEGER; backColor: INTEGER);
|
|
VAR
|
|
k, j, Start, End: INTEGER;
|
|
c: WCHAR;
|
|
BEGIN
|
|
k := i;
|
|
Lang.SkipString(line, i, line.length - 1, text.lang);
|
|
PrintLex(text, line, k, i, y, colors.string, backColor);
|
|
IF text.lang IN Lang.escLang THEN
|
|
Start := k + 1;
|
|
End := i - 1;
|
|
k := Start;
|
|
WHILE k <= End DO
|
|
c := Lines.getChar(line, k);
|
|
IF c = "\" THEN
|
|
j := k;
|
|
Lang.SkipEsc(line, k, line.length - 1, text.lang);
|
|
PrintLex(text, line, j, k, y, colors.escape, backColor)
|
|
END;
|
|
INC(k)
|
|
END
|
|
END
|
|
END String;
|
|
|
|
|
|
BEGIN
|
|
depth := line.cin;
|
|
n := line.length - 1;
|
|
i := 0;
|
|
IF (depth > 0) & (n >= 0) THEN
|
|
PrintComment(text, line, depth, i, 2, y, backColor)
|
|
END;
|
|
cond := 0;
|
|
WHILE i <= n DO
|
|
c := Lines.getChar(line, i);
|
|
|
|
IF lang = Lang.langFasm THEN
|
|
|
|
IF c = ";" THEN
|
|
PrintLex(text, line, i, n, y, colors.comment, backColor);
|
|
i := n
|
|
ELSIF (c = "'") OR (c = '"') THEN
|
|
String(text, line, i, y, backColor)
|
|
ELSIF (U.isLetter(c) OR (c = "_")) THEN
|
|
ident(text, i, i, y, line, backColor, Lang.isCS(lang))
|
|
ELSIF U.isDigit(c) THEN
|
|
hex := FALSE;
|
|
k := i;
|
|
INC(i);
|
|
c := Lines.getChar(line, i);
|
|
IF (upper(c) = "X") & (Lines.getChar(line, i - 1) = "0") THEN
|
|
INC(i);
|
|
hex := TRUE
|
|
END;
|
|
|
|
WHILE U.isHex(upper(Lines.getChar(line, i))) DO
|
|
INC(i)
|
|
END;
|
|
|
|
IF (upper(Lines.getChar(line, i)) = "H") & ~hex THEN
|
|
INC(i)
|
|
END;
|
|
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.num, backColor)
|
|
END
|
|
|
|
ELSIF (lang = Lang.langC) OR (lang = Lang.langJSON) THEN
|
|
|
|
IF depth = 0 THEN
|
|
IF c = "/" THEN
|
|
IF cond = 0 THEN
|
|
cond := 1
|
|
ELSE
|
|
PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
|
|
cond := 0;
|
|
i := n
|
|
END
|
|
ELSIF (c = "*") & (cond = 1) THEN
|
|
depth := 1;
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 2, y, backColor);
|
|
cond := 0
|
|
ELSIF U.isLetter(c) OR (c = "_") OR (c = "'") OR (c = '"') THEN
|
|
k := i;
|
|
IF (c = "'") OR (c = '"') THEN
|
|
String(text, line, i, y, backColor);
|
|
ELSE
|
|
ident(text, i, i - ORD((lang = Lang.langC) & (i > 0) & (Lines.getChar(line, i - 1) = "#")), y, line, backColor, Lang.isCS(lang))
|
|
END;
|
|
IF lang = Lang.langJSON THEN
|
|
WHILE Lines.isSpace(Lines.getChar(line, i + 1)) DO
|
|
INC(i)
|
|
END;
|
|
IF Lines.getChar(line, i + 1) = ":" THEN
|
|
PrintLex(text, line, k, i, y, colors.key1, backColor)
|
|
END
|
|
END;
|
|
cond := 0
|
|
ELSIF U.isDigit(c) THEN
|
|
k := i;
|
|
INC(i);
|
|
c := Lines.getChar(line, i);
|
|
IF c = "." THEN
|
|
DEC(i);
|
|
c := Lines.getChar(line, i)
|
|
END;
|
|
IF (upper(c) = "X") & (Lines.getChar(line, i - 1) = "0") THEN
|
|
REPEAT
|
|
INC(i);
|
|
c := Lines.getChar(line, i)
|
|
UNTIL ~U.isHex(upper(c));
|
|
IF UL(c) THEN
|
|
INC(i)
|
|
END
|
|
ELSIF UL(c) THEN
|
|
INC(i)
|
|
ELSIF U.isDigit(c) THEN
|
|
REPEAT
|
|
INC(i)
|
|
UNTIL ~U.isDigit(Lines.getChar(line, i));
|
|
c := Lines.getChar(line, i);
|
|
IF UL(c) THEN
|
|
INC(i)
|
|
ELSIF c = "." THEN
|
|
INC(i);
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
c := Lines.getChar(line, i);
|
|
IF upper(c) = "E" THEN
|
|
INC(i);
|
|
c := Lines.getChar(line, i);
|
|
IF (c = "+") OR (c = "-") THEN
|
|
INC(i)
|
|
END;
|
|
IF U.isDigit(Lines.getChar(line, i)) THEN
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
c := Lines.getChar(line, i);
|
|
IF FL(c) THEN
|
|
INC(i)
|
|
END
|
|
END
|
|
ELSIF FL(c) THEN
|
|
INC(i)
|
|
END
|
|
END
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.num, backColor);
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
ELSIF depth = 1 THEN
|
|
IF c = "*" THEN
|
|
cond := 1
|
|
ELSIF (c = "/") & (cond = 1) THEN
|
|
cond := 0;
|
|
depth := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
END
|
|
|
|
ELSIF lang = Lang.langOberon THEN
|
|
|
|
IF (depth = 0) & (c = "/") THEN
|
|
IF cond = 3 THEN
|
|
PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
|
|
cond := 0;
|
|
i := n
|
|
ELSE
|
|
cond := 3
|
|
END
|
|
ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
|
|
String(text, line, i, y, backColor);
|
|
cond := 0
|
|
ELSIF (depth = 0) & U.isDigit(c) THEN
|
|
color := colors.num;
|
|
k := i;
|
|
INC(i);
|
|
WHILE U.isHex(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
IF i <= n THEN
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
INC(i);
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
DEC(i)
|
|
END;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
IF upper(Lines.getChar(line, i)) = "E" THEN
|
|
INC(i);
|
|
IF (Lines.getChar(line, i) = "+") OR (Lines.getChar(line, i) = "-") THEN
|
|
INC(i)
|
|
END;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END
|
|
END
|
|
ELSIF upper(Lines.getChar(line, i)) = "H" THEN
|
|
INC(i)
|
|
ELSIF upper(Lines.getChar(line, i)) = "X" THEN
|
|
color := colors.string;
|
|
INC(i)
|
|
END
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, color, backColor);
|
|
cond := 0
|
|
ELSIF (depth = 0) & (U.isLetter(c) OR (c = "_")) THEN
|
|
ident(text, i, i, y, line, backColor, Lang.isCS(lang));
|
|
cond := 0
|
|
ELSIF c = "(" THEN
|
|
cond := 1
|
|
ELSIF c = "*" THEN
|
|
IF cond = 1 THEN
|
|
INC(depth);
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 2, y, backColor);
|
|
cond := 0
|
|
ELSE
|
|
cond := 2
|
|
END
|
|
ELSIF c = ")" THEN
|
|
IF cond = 2 THEN
|
|
IF depth > 0 THEN
|
|
DEC(depth)
|
|
END
|
|
END;
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
|
|
ELSIF lang = Lang.langLua THEN
|
|
|
|
IF depth = 0 THEN
|
|
IF c = "-" THEN
|
|
IF cond = 1 THEN
|
|
IF Lang.LuaLong(line, i + 1) >= 0 THEN
|
|
depth := Lang.LuaLong(line, i + 1)*2 + 1;
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 2, y, backColor)
|
|
ELSE
|
|
PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
|
|
i := n
|
|
END;
|
|
cond := 0
|
|
ELSE
|
|
cond := 1
|
|
END
|
|
ELSIF c = "[" THEN
|
|
cond := 0;
|
|
k := Lang.LuaLong(line, i);
|
|
IF k >= 0 THEN
|
|
depth := (k + 1)*2;
|
|
INC(i, 2);
|
|
PrintComment(text, line, depth, i, 2, y, backColor);
|
|
cond := 0
|
|
END
|
|
ELSIF (c = "'") OR (c = '"') THEN
|
|
String(text, line, i, y, backColor);
|
|
cond := 0
|
|
ELSIF U.isDigit(c) THEN
|
|
k := i;
|
|
IF (c = "0") & (upper(Lines.getChar(line, i + 1)) = "X") THEN
|
|
isDgt := U.isHex;
|
|
hex := TRUE;
|
|
INC(i, 2)
|
|
ELSE
|
|
isDgt := U.isDigit;
|
|
hex := FALSE
|
|
END;
|
|
WHILE isDgt(upper(Lines.getChar(line, i))) DO
|
|
INC(i)
|
|
END;
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
INC(i);
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
DEC(i)
|
|
END;
|
|
WHILE isDgt(upper(Lines.getChar(line, i))) DO
|
|
INC(i)
|
|
END
|
|
END;
|
|
IF (upper(Lines.getChar(line, i)) = "E") OR hex & (upper(Lines.getChar(line, i)) = "P") THEN
|
|
INC(i);
|
|
IF (Lines.getChar(line, i) = "-") OR (Lines.getChar(line, i) = "+") THEN
|
|
INC(i)
|
|
END;
|
|
WHILE isDgt(upper(Lines.getChar(line, i))) DO
|
|
INC(i)
|
|
END
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.num, backColor);
|
|
cond := 0
|
|
ELSIF U.isLetter(c) OR (c = "_") THEN
|
|
ident(text, i, i, y, line, backColor, Lang.isCS(lang));
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
|
|
ELSIF depth > 0 THEN
|
|
IF (cond = 0) & (c = "]") THEN
|
|
cond := 1
|
|
ELSIF (cond >= 1) & (c = "=") THEN
|
|
INC(cond)
|
|
ELSIF (cond >= 1) & (c = "]") & (cond * 2 - depth MOD 2 = depth) THEN
|
|
depth := 0;
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
END
|
|
|
|
ELSIF lang = Lang.langPascal THEN
|
|
|
|
IF depth = 0 THEN
|
|
IF c = "(" THEN
|
|
cond := 1
|
|
ELSIF (c = "*") & (cond = 1) THEN
|
|
depth := 2;
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 2, y, backColor);
|
|
cond := 0
|
|
ELSIF c = "/" THEN
|
|
IF cond = 2 THEN
|
|
PrintLex(text, line, i - 1, n, y, colors.comment, backColor);
|
|
cond := 0;
|
|
i := n
|
|
ELSE
|
|
cond := 2
|
|
END
|
|
ELSIF c = "'" THEN
|
|
String(text, line, i, y, backColor);
|
|
cond := 0
|
|
ELSIF c = "{" THEN
|
|
IF Lines.getChar(line, i + 1) = "$" THEN
|
|
depth := 3
|
|
ELSE
|
|
depth := 1
|
|
END;
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 1, y, backColor);
|
|
cond := 0
|
|
ELSIF c = "#" THEN
|
|
k := i;
|
|
INC(i);
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.string, backColor);
|
|
cond := 0
|
|
ELSIF c = "$" THEN
|
|
IF (i > 0 ) & (Lines.getChar(line, i - 1) = "#") THEN
|
|
color := colors.string
|
|
ELSE
|
|
color := colors.num
|
|
END;
|
|
k := i;
|
|
INC(i);
|
|
WHILE U.isHex(upper(Lines.getChar(line, i))) DO
|
|
INC(i)
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, color, backColor);
|
|
cond := 0
|
|
ELSIF U.isDigit(c) THEN
|
|
k := i;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
INC(i);
|
|
IF Lines.getChar(line, i) = "." THEN
|
|
DEC(i)
|
|
END;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
IF upper(Lines.getChar(line, i)) = "E" THEN
|
|
INC(i);
|
|
IF (Lines.getChar(line, i) = "-") OR (Lines.getChar(line, i) = "+") THEN
|
|
INC(i)
|
|
END;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END
|
|
END
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.num, backColor);
|
|
cond := 0
|
|
ELSIF (U.isLetter(c) OR (c = "_")) THEN
|
|
ident(text, i, i, y, line, backColor, Lang.isCS(lang));
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
ELSIF depth IN {1, 3} THEN
|
|
IF c = "}" THEN
|
|
depth := 0
|
|
END
|
|
ELSIF depth = 2 THEN
|
|
IF c = "*" THEN
|
|
cond := 1
|
|
ELSIF (c = ")") & (cond = 1) THEN
|
|
depth := 0;
|
|
cond := 0
|
|
ELSE
|
|
cond := 0
|
|
END
|
|
END
|
|
|
|
ELSIF lang = Lang.langIni THEN
|
|
|
|
IF depth = 0 THEN
|
|
IF ((c = ";") OR (c = "#")) & (leadingSpaces(line) = i) THEN
|
|
PrintLex(text, line, i, n, y, colors.comment, backColor);
|
|
i := n
|
|
ELSIF c = '"' THEN
|
|
String(text, line, i, y, backColor)
|
|
ELSIF c = "[" THEN
|
|
depth := 1;
|
|
INC(i);
|
|
PrintComment(text, line, depth, i, 1, y, backColor)
|
|
ELSIF U.isDigit(c) THEN
|
|
k := i;
|
|
WHILE U.isDigit(Lines.getChar(line, i)) DO
|
|
INC(i)
|
|
END;
|
|
DEC(i);
|
|
PrintLex(text, line, k, i, y, colors.num, backColor)
|
|
ELSIF (U.isLetter(c) OR (c = "_")) THEN
|
|
ident(text, i, i, y, line, backColor, Lang.isCS(lang))
|
|
END
|
|
ELSIF depth = 1 THEN
|
|
IF c = "]" THEN
|
|
depth := 0
|
|
END
|
|
END
|
|
|
|
END;
|
|
INC(i)
|
|
END
|
|
END parse;
|
|
|
|
|
|
PROCEDURE plain (text: tText; textStart, textEnd: tPoint; _copy: BOOLEAN): CB.tBuffer;
|
|
VAR
|
|
first, line: tLine;
|
|
cnt, n: INTEGER;
|
|
buffer: CB.tBuffer;
|
|
|
|
|
|
PROCEDURE append (buffer: CB.tBuffer; line: tLine; first, last: INTEGER; _copy: BOOLEAN);
|
|
BEGIN
|
|
IF first <= last THEN
|
|
CB.append(buffer, line, first, last)
|
|
ELSE
|
|
IF (U.OS = "KOS") & _copy THEN
|
|
CB.appends(buffer, SPACE, 0, 0)
|
|
END
|
|
END
|
|
END append;
|
|
|
|
|
|
BEGIN
|
|
first := getLine2(text, textStart.Y);
|
|
line := first;
|
|
|
|
n := textEnd.Y - textStart.Y;
|
|
cnt := 0;
|
|
WHILE n >= 0 DO
|
|
INC(cnt, line.length + lenEOL);
|
|
IF (U.OS = "KOS") & _copy & (line.length = 0) THEN
|
|
INC(cnt)
|
|
END;
|
|
NextLine(line);
|
|
DEC(n)
|
|
END;
|
|
|
|
buffer := CB.create(cnt + 2); (* +2 wchars EOT *)
|
|
|
|
n := textEnd.Y - textStart.Y;
|
|
line := first;
|
|
IF n = 0 THEN
|
|
append(buffer, line, textStart.X, textEnd.X - 1, _copy)
|
|
ELSE
|
|
append(buffer, line, textStart.X, line.length - 1, _copy);
|
|
REPEAT
|
|
DEC(n);
|
|
CB.eol(buffer);
|
|
NextLine(line);
|
|
IF n > 0 THEN
|
|
append(buffer, line, 0, line.length - 1, _copy)
|
|
END
|
|
UNTIL n = 0;
|
|
append(buffer, line, 0, textEnd.X - 1, _copy)
|
|
END
|
|
|
|
RETURN buffer
|
|
END plain;
|
|
|
|
|
|
PROCEDURE ClearSearch (text: tText);
|
|
VAR
|
|
pos: List.tItem;
|
|
line: tLine;
|
|
cnt: INTEGER;
|
|
BEGIN
|
|
cnt := -lenEOL;
|
|
line := text.first(tLine);
|
|
WHILE line # NIL DO
|
|
INC(cnt, lenEOL);
|
|
line.pos := cnt;
|
|
INC(cnt, line.length);
|
|
NextLine(line)
|
|
END;
|
|
|
|
WHILE text.foundList.count # 0 DO
|
|
pos := List.pop(text.foundList);
|
|
DISPOSE(pos)
|
|
END
|
|
END ClearSearch;
|
|
|
|
|
|
PROCEDURE _search (text: tText; s: ARRAY OF WCHAR; cs, whole: BOOLEAN; textStart, textEnd: tPoint): BOOLEAN;
|
|
VAR
|
|
res: BOOLEAN;
|
|
plainText, idxData: CB.tBuffer;
|
|
first: tLine;
|
|
|
|
BEGIN
|
|
res := TRUE;
|
|
plainText := NIL;
|
|
idxData := NIL;
|
|
text.whole := whole;
|
|
text.cs := cs;
|
|
text.searchText := s;
|
|
IF ~cs THEN
|
|
U.lowcase(text.searchText)
|
|
END;
|
|
IF text.searchText # "" THEN
|
|
first := getLine2(text, textStart.Y);
|
|
plainText := plain(text, textStart, textEnd, FALSE);
|
|
CB.appends(plainText, 0X, 0, 0);
|
|
CB.appends(plainText, 0X, 0, 0);
|
|
idxData := Search.index(plainText, cs);
|
|
Search.find(plainText, text.searchText, whole, text.foundList, first.pos + textStart.X);
|
|
res := text.foundList.count > 0
|
|
ELSE
|
|
Search.close
|
|
END;
|
|
CB.destroy(plainText);
|
|
CB.destroy(idxData);
|
|
text.search := FALSE;
|
|
text.foundSel := 0
|
|
RETURN res
|
|
END _search;
|
|
|
|
|
|
PROCEDURE search* (text: tText; s: ARRAY OF WCHAR; cs, whole: BOOLEAN): BOOLEAN;
|
|
VAR
|
|
textStart, textEnd: tPoint;
|
|
BEGIN
|
|
textStart.Y := 0; textStart.X := 0;
|
|
textEnd.Y := text.count - 1; textEnd.X := text.last(tLine).length;
|
|
ClearSearch(text)
|
|
RETURN _search(text, s, cs, whole, textStart, textEnd)
|
|
END search;
|
|
|
|
|
|
PROCEDURE fasm_anon (text: tText);
|
|
VAR
|
|
textStart, textEnd: tPoint;
|
|
res, frw, back, label, anon_label: BOOLEAN;
|
|
Y1, Y2, i, k, j: INTEGER;
|
|
line, Label: tLine;
|
|
str: ARRAY 8 OF WCHAR;
|
|
|
|
|
|
PROCEDURE anon (line: tLine): BOOLEAN;
|
|
VAR
|
|
i: INTEGER;
|
|
BEGIN
|
|
i := leadingSpaces(line)
|
|
RETURN (Lines.getChar(line, i) = "@") &
|
|
(Lines.getChar(line, i + 1) = "@") &
|
|
(Lines.getChar(line, i + 2) = ":")
|
|
END anon;
|
|
|
|
|
|
BEGIN
|
|
frw := FALSE;
|
|
back := FALSE;
|
|
label := FALSE;
|
|
line := text.curLine;
|
|
|
|
i := text.cursor.X;
|
|
j := 0;
|
|
FOR k := i - 3 TO i + 2 DO
|
|
str[j] := U.lcase(Lines.getChar(line, k));
|
|
INC(j)
|
|
END;
|
|
j := 3;
|
|
|
|
anon_label := anon(line);
|
|
|
|
IF str[j] = "@" THEN
|
|
IF str[j + 1] = "f" THEN
|
|
frw := TRUE
|
|
ELSIF (str[j + 1] = "b") OR (str[j + 1] = "r") THEN
|
|
back := TRUE
|
|
ELSIF anon_label & (((str[j + 1] = "@") & (str[j + 2] = ":")) OR
|
|
((str[j - 1] = "@") & (str[j + 1] = ":"))) THEN
|
|
label := TRUE
|
|
END
|
|
ELSIF str[j - 1] = "@" THEN
|
|
IF str[j] = "f" THEN
|
|
frw := TRUE
|
|
ELSIF (str[j] = "b") OR (str[j] = "r") THEN
|
|
back := TRUE
|
|
ELSIF anon_label & (str[j] = ":") & (str[j - 2] = "@") THEN
|
|
label := TRUE
|
|
END
|
|
ELSIF anon_label & (str[j] = ":") & (str[j - 1] = "@") & (str[j - 2] = "@") THEN
|
|
label := TRUE
|
|
ELSIF (str[j - 1] = "f") & (str[j - 2] = "@") THEN
|
|
frw := TRUE
|
|
ELSIF ((str[j - 1] = "b") OR (str[j - 1] = "r")) & (str[j - 2] = "@") THEN
|
|
back := TRUE
|
|
ELSIF anon_label & (str[j - 1] = ":") & (str[j - 2] = "@") & (str[j - 3] = "@") THEN
|
|
label := TRUE
|
|
END;
|
|
|
|
IF back OR frw OR label THEN
|
|
Y1 := text.cursor.Y;
|
|
Y2 := Y1;
|
|
|
|
IF label THEN
|
|
Label := line;
|
|
DEC(Y1)
|
|
ELSE
|
|
Label := NIL
|
|
END;
|
|
|
|
line := getLine2(text, Y1);
|
|
WHILE (Y1 > 0) & ~anon(line) DO
|
|
PrevLine(line);
|
|
DEC(Y1)
|
|
END;
|
|
|
|
line := getLine2(text, Y2);
|
|
IF anon(line) THEN
|
|
NextLine(line);
|
|
INC(Y2)
|
|
END;
|
|
|
|
WHILE (Y2 < text.count) & ~anon(line) DO
|
|
NextLine(line);
|
|
INC(Y2)
|
|
END;
|
|
|
|
IF Y1 < 0 THEN
|
|
Y1 := 0
|
|
ELSIF back THEN
|
|
Label := getLine2(text, Y1)
|
|
END;
|
|
textStart.Y := Y1; textStart.X := 0;
|
|
IF Y2 = text.count THEN
|
|
DEC(Y2);
|
|
textEnd.X := text.last(tLine).length
|
|
ELSIF frw THEN
|
|
Label := getLine2(text, Y2);
|
|
textEnd.X := 0
|
|
END;
|
|
textEnd.Y := Y2;
|
|
ClearSearch(text);
|
|
text.smallMove := FALSE;
|
|
IF (Label # NIL) & ~anon(Label) THEN
|
|
Label := NIL
|
|
END
|
|
END;
|
|
|
|
IF frw THEN
|
|
res := _search(text, "@f", FALSE, FALSE, textStart, textEnd);
|
|
IF Label # NIL THEN
|
|
Search.add(text.foundList, Label.pos + leadingSpaces(Label))
|
|
END
|
|
ELSIF back THEN
|
|
IF Label # NIL THEN
|
|
Search.add(text.foundList, Label.pos + leadingSpaces(Label))
|
|
END;
|
|
res := _search(text, "@b", FALSE, FALSE, textStart, textEnd);
|
|
res := _search(text, "@r", FALSE, FALSE, textStart, textEnd)
|
|
ELSIF label THEN
|
|
res := _search(text, "@f", FALSE, FALSE, textStart, text.cursor^);
|
|
IF Label # NIL THEN
|
|
Search.add(text.foundList, Label.pos + leadingSpaces(Label))
|
|
END;
|
|
res := _search(text, "@b", FALSE, FALSE, text.cursor^, textEnd);
|
|
res := _search(text, "@r", FALSE, FALSE, text.cursor^, textEnd)
|
|
END
|
|
END fasm_anon;
|
|
|
|
|
|
PROCEDURE modify (text: tText);
|
|
BEGIN
|
|
text.modified := TRUE;
|
|
text.comments := TRUE;
|
|
text.search := TRUE;
|
|
text.guard := TRUE;
|
|
text.wordSel := TRUE
|
|
END modify;
|
|
|
|
|
|
PROCEDURE setEnc* (text: tText; enc: INTEGER);
|
|
BEGIN
|
|
IF text.enc # enc THEN
|
|
ChangeLog.changeInt(text.enc, enc);
|
|
text.enc := enc;
|
|
modify(text)
|
|
END
|
|
END setEnc;
|
|
|
|
|
|
PROCEDURE setEol* (text: tText; eol: INTEGER);
|
|
BEGIN
|
|
IF text.eol # eol THEN
|
|
ChangeLog.changeInt(text.eol, eol);
|
|
text.eol := eol;
|
|
modify(text)
|
|
END
|
|
END setEol;
|
|
|
|
|
|
PROCEDURE getEnc* (text: tText): INTEGER;
|
|
RETURN text.enc
|
|
END getEnc;
|
|
|
|
|
|
PROCEDURE getEol* (text: tText): INTEGER;
|
|
RETURN text.eol
|
|
END getEol;
|
|
|
|
|
|
PROCEDURE DelLine (text: tText; line: tLine);
|
|
BEGIN
|
|
List._delete(text, line);
|
|
Lines.destroy(line);
|
|
modify(text)
|
|
END DelLine;
|
|
|
|
|
|
PROCEDURE setSelect (text: tText);
|
|
BEGIN
|
|
IF text.select = text.cursor THEN
|
|
text.select2^ := text.cursor^;
|
|
text.select := text.select2
|
|
END
|
|
END setSelect;
|
|
|
|
|
|
PROCEDURE resetSelect* (text: tText);
|
|
BEGIN
|
|
text.select := text.cursor
|
|
END resetSelect;
|
|
|
|
|
|
PROCEDURE getLine (text: tText; n: INTEGER): tLine;
|
|
VAR
|
|
item: List.tItem;
|
|
BEGIN
|
|
item := List.getItem(text, n)
|
|
RETURN item(tLine)
|
|
END getLine;
|
|
|
|
|
|
PROCEDURE SetPos* (text: tText; x, y: INTEGER);
|
|
VAR
|
|
deltaY, n, L, R: INTEGER;
|
|
cursor: pPoint;
|
|
c: WCHAR;
|
|
(* trimLength: INTEGER; *)
|
|
BEGIN
|
|
cursor := text.cursor;
|
|
y := MIN(MAX(y, 0), text.count - 1);
|
|
deltaY := y - cursor.Y;
|
|
IF deltaY # 0 THEN
|
|
cursor.Y := y;
|
|
(* trimLength := Lines.trimLength(text.curLine);
|
|
IF text.curLine.length # trimLength THEN
|
|
Lines.setChar(text.curLine, trimLength, 0X);
|
|
text.curLine.length := trimLength
|
|
END;*)
|
|
IF deltaY = 1 THEN
|
|
NextLine(text.curLine)
|
|
ELSIF deltaY = -1 THEN
|
|
PrevLine(text.curLine)
|
|
ELSE
|
|
text.curLine := getLine(text, y)
|
|
END
|
|
END;
|
|
cursor.X := MIN(MAX(x, 0), text.curLine.length);
|
|
c := Lines.getChar(text.curLine, cursor.X);
|
|
IF c = TAB1 THEN
|
|
n := cursor.X;
|
|
WHILE Lines.getChar(text.curLine, n) = TAB1 DO
|
|
INC(n)
|
|
END;
|
|
R := n - cursor.X;
|
|
n := cursor.X;
|
|
WHILE Lines.getChar(text.curLine, n) # TAB DO
|
|
DEC(n)
|
|
END;
|
|
L := cursor.X - n;
|
|
IF L < R THEN
|
|
DEC(cursor.X, L)
|
|
ELSE
|
|
INC(cursor.X, R)
|
|
END
|
|
END;
|
|
IF text.scroll.Y > cursor.Y THEN
|
|
text.scroll.Y := cursor.Y
|
|
ELSIF text.scroll.Y + textsize.Y <= cursor.Y THEN
|
|
text.scroll.Y := cursor.Y - textsize.Y + 1
|
|
END;
|
|
IF text.scroll.X > cursor.X THEN
|
|
text.scroll.X := cursor.X
|
|
ELSIF text.scroll.X + textsize.X <= cursor.X THEN
|
|
text.scroll.X := cursor.X - textsize.X + 1
|
|
END;
|
|
IF (text.select.Y = cursor.Y) & (text.select.X > text.curLine.length) THEN
|
|
text.select.X := text.curLine.length
|
|
END;
|
|
setSelect(text);
|
|
text.foundSel := 0;
|
|
ShowCursor;
|
|
text.CurX := -1;
|
|
text.wordSel := TRUE
|
|
END SetPos;
|
|
|
|
|
|
PROCEDURE getSelect (text: tText; VAR selBeg, selEnd: tPoint);
|
|
BEGIN
|
|
selBeg := text.cursor^;
|
|
selEnd := text.select^;
|
|
IF (selBeg.Y > selEnd.Y) OR (selBeg.Y = selEnd.Y) & (selBeg.X > selEnd.X) THEN
|
|
selBeg := text.select^;
|
|
selEnd := text.cursor^
|
|
END
|
|
END getSelect;
|
|
|
|
|
|
PROCEDURE selected* (text: tText): BOOLEAN;
|
|
RETURN (text.cursor.X # text.select.X) OR (text.cursor.Y # text.select.Y)
|
|
END selected;
|
|
|
|
|
|
PROCEDURE delSelect (text: tText);
|
|
VAR
|
|
selBeg, selEnd: tPoint;
|
|
line, last, cur: tLine;
|
|
BEGIN
|
|
getSelect(text, selBeg, selEnd);
|
|
IF (selBeg.Y = selEnd.Y) & (selBeg.X < selEnd.X) THEN
|
|
line := text.curLine;
|
|
Lines.delCharN(line, selBeg.X, selEnd.X - selBeg.X);
|
|
Lines.modify(line);
|
|
text.cursor^ := selBeg;
|
|
resetSelect(text);
|
|
SetPos(text, text.cursor.X, text.cursor.Y);
|
|
modify(text)
|
|
ELSIF selBeg.Y < selEnd.Y THEN
|
|
SetPos(text, selBeg.X, selBeg.Y);
|
|
line := text.curLine;
|
|
Lines.delCharN(line, selBeg.X, line.length - selBeg.X);
|
|
last := getLine(text, selEnd.Y);
|
|
Lines.delCharN(last, 0, selEnd.X);
|
|
cur := line.next(tLine);
|
|
WHILE cur # last DO
|
|
DelLine(text, cur);
|
|
cur := line.next(tLine)
|
|
END;
|
|
resetSelect(text);
|
|
SetPos(text, text.cursor.X, text.cursor.Y);
|
|
pdelete(text);
|
|
modify(text)
|
|
END;
|
|
resetSelect(text)
|
|
END delSelect;
|
|
|
|
|
|
PROCEDURE delete (text: tText);
|
|
VAR
|
|
i, n: INTEGER;
|
|
nextLine, curLine: tLine;
|
|
BEGIN
|
|
IF selected(text) THEN
|
|
delSelect(text)
|
|
ELSE
|
|
i := text.cursor.X;
|
|
curLine := text.curLine;
|
|
IF i < curLine.length THEN
|
|
n := i;
|
|
INC(i);
|
|
IF Lines.getChar(curLine, i - 1) = TAB THEN
|
|
WHILE Lines.getChar(curLine, i) = TAB1 DO
|
|
INC(i)
|
|
END
|
|
END;
|
|
Lines.delCharN(curLine, n, i - n);
|
|
Lines.modify(curLine);
|
|
modify(text)
|
|
ELSE
|
|
nextLine := curLine.next(tLine);
|
|
IF nextLine # NIL THEN
|
|
Lines.insert2(curLine, i, nextLine);
|
|
DelLine(text, nextLine);
|
|
Lines.modify(curLine);
|
|
modify(text)
|
|
END
|
|
END
|
|
END;
|
|
setSelect(text)
|
|
END delete;
|
|
|
|
|
|
PROCEDURE move (text: tText; d: INTEGER);
|
|
VAR
|
|
pos: INTEGER;
|
|
BEGIN
|
|
pos := text.cursor.X + d;
|
|
WHILE Lines.getChar(text.curLine, pos) = TAB1 DO
|
|
INC(pos, d)
|
|
END;
|
|
SetPos(text, pos, text.cursor.Y)
|
|
END move;
|
|
|
|
|
|
PROCEDURE BkSpace (text: tText);
|
|
VAR
|
|
i, k, n: INTEGER;
|
|
curLine, line, line2: tLine;
|
|
BEGIN
|
|
IF selected(text) THEN
|
|
delSelect(text)
|
|
ELSE
|
|
resetSelect(text);
|
|
curLine := text.curLine;
|
|
IF text.cursor.X > 0 THEN
|
|
INC(text.smallChange);
|
|
i := text.cursor.X;
|
|
IF autoIndents THEN
|
|
n := leadingSpaces(curLine)
|
|
ELSE
|
|
n := 0
|
|
END;
|
|
modify(text);
|
|
IF n < i THEN
|
|
move(text, -1);
|
|
delete(text)
|
|
ELSE
|
|
n := i;
|
|
line := curLine.prev(tLine);
|
|
line2 := line;
|
|
k := n;
|
|
WHILE (line # NIL) & (k >= n) DO
|
|
IF Lines.trimLength(line) # 0 THEN
|
|
k := leadingSpaces(line);
|
|
line2 := line;
|
|
END;
|
|
PrevLine(line)
|
|
END;
|
|
IF k >= n THEN
|
|
k := 0
|
|
END;
|
|
n := k;
|
|
Lines.delCharN(curLine, 0, i);
|
|
Lines.insert3(curLine, 0, k);
|
|
WHILE k > 0 DO
|
|
Lines.setChar(curLine, k - 1, Lines.getChar(line2, k - 1));
|
|
DEC(k)
|
|
END;
|
|
Lines.modify(curLine);
|
|
SetPos(text, n, text.cursor.Y)
|
|
END
|
|
ELSE
|
|
PrevLine(curLine);
|
|
IF curLine # NIL THEN
|
|
SetPos(text, curLine.length, text.cursor.Y - 1);
|
|
delete(text)
|
|
END
|
|
END
|
|
END;
|
|
setSelect(text)
|
|
END BkSpace;
|
|
|
|
|
|
PROCEDURE enter (text: tText);
|
|
VAR
|
|
n: INTEGER;
|
|
curLine, newLine, line, line2: tLine;
|
|
BEGIN
|
|
delSelect(text);
|
|
newLine := Lines.create(FALSE);
|
|
modify(text);
|
|
curLine := text.curLine;
|
|
IF text.cursor.X < curLine.length THEN
|
|
Lines.wrap(curLine, newLine, text.cursor.X);
|
|
Lines.modify(curLine)
|
|
END;
|
|
List._insert(text, curLine, newLine);
|
|
SetPos(text, 0, text.cursor.Y + 1);
|
|
line := text.curLine.prev(tLine);
|
|
n := -1;
|
|
WHILE (line # NIL) & (n = -1) & autoIndents DO
|
|
IF (*line.length*)Lines.trimLength(line) # 0 THEN
|
|
n := leadingSpaces(line);
|
|
line2 := line
|
|
END;
|
|
PrevLine(line)
|
|
END;
|
|
IF n = -1 THEN
|
|
n := 0
|
|
END;
|
|
Lines.insert3(text.curLine, 0, n);
|
|
SetPos(text, n, text.cursor.Y);
|
|
resetSelect(text);
|
|
WHILE n > 0 DO
|
|
Lines.setChar(text.curLine, n - 1, Lines.getChar(line2, n - 1));
|
|
DEC(n)
|
|
END;
|
|
Lines.modify(newLine);
|
|
SetPos(text, text.cursor.X, text.cursor.Y)
|
|
END enter;
|
|
|
|
|
|
PROCEDURE incIndent (line: tLine);
|
|
VAR
|
|
c: WCHAR;
|
|
i: INTEGER;
|
|
BEGIN
|
|
Lines.modify(line);
|
|
Lines.insert3(line, 0, Lines.tab);
|
|
IF Lines.tabs THEN
|
|
c := TAB1
|
|
ELSE
|
|
c := SPACE
|
|
END;
|
|
i := Lines.tab - 1;
|
|
WHILE i >= 0 DO
|
|
Lines.setChar(line, i, c);
|
|
DEC(i)
|
|
END;
|
|
IF Lines.tabs THEN
|
|
Lines.setChar(line, 0, TAB)
|
|
END
|
|
END incIndent;
|
|
|
|
|
|
PROCEDURE decIndent (line: tLine): BOOLEAN;
|
|
VAR
|
|
n: INTEGER;
|
|
BEGIN
|
|
n := leadingSpaces(line);
|
|
IF n > 0 THEN
|
|
Lines.delCharN(line, 0, MIN(Lines.tab, n));
|
|
Lines.modify(line)
|
|
END
|
|
RETURN n > 0
|
|
END decIndent;
|
|
|
|
|
|
PROCEDURE Indent* (text: tText; incr: BOOLEAN);
|
|
VAR
|
|
i: INTEGER;
|
|
line: tLine;
|
|
selBeg, selEnd: tPoint;
|
|
modified: BOOLEAN;
|
|
BEGIN
|
|
getSelect(text, selBeg, selEnd);
|
|
i := selEnd.Y - selBeg.Y + 1;
|
|
line := getLine2(text, selBeg.Y);
|
|
modified := incr;
|
|
WHILE i > 0 DO
|
|
IF incr THEN
|
|
incIndent(line)
|
|
ELSE
|
|
modified := decIndent(line) OR modified
|
|
END;
|
|
NextLine(line);
|
|
DEC(i)
|
|
END;
|
|
line := getLine2(text, selEnd.Y);
|
|
text.select^ := selBeg;
|
|
text.select.X := 0;
|
|
SetPos(text, line.length, selEnd.Y);
|
|
IF modified THEN
|
|
INC(text.smallChange);
|
|
modify(text)
|
|
END
|
|
END Indent;
|
|
|
|
|
|
PROCEDURE input* (text: tText; code: INTEGER);
|
|
VAR
|
|
curLine: tLine;
|
|
|
|
|
|
PROCEDURE tab (text: tText);
|
|
VAR
|
|
i, x: INTEGER;
|
|
curLine: tLine;
|
|
c: WCHAR;
|
|
BEGIN
|
|
delSelect(text);
|
|
curLine := text.curLine;
|
|
x := text.cursor.X;
|
|
i := Lines.tab - x MOD Lines.tab;
|
|
Lines.insert3(curLine, x, i);
|
|
SetPos(text, x + i, text.cursor.Y);
|
|
IF Lines.tabs THEN
|
|
c := TAB1
|
|
ELSE
|
|
c := SPACE
|
|
END;
|
|
WHILE i > 0 DO
|
|
Lines.setChar(curLine, x + i - 1, c);
|
|
DEC(i)
|
|
END;
|
|
IF Lines.tabs THEN
|
|
Lines.setChar(curLine, x + i, TAB)
|
|
END;
|
|
Lines.modify(curLine);
|
|
modify(text)
|
|
END tab;
|
|
|
|
|
|
BEGIN
|
|
IF (code >= ORD(SPACE)) & (code # 127) THEN
|
|
IF ~selected(text) THEN
|
|
INC(text.smallChange)
|
|
END;
|
|
delSelect(text);
|
|
curLine := text.curLine;
|
|
Lines.insert(curLine, text.cursor.X, WCHR(code));
|
|
IF autoBrackets THEN
|
|
IF code = ORD("(") THEN
|
|
code := ORD(")")
|
|
ELSIF code = ORD("[") THEN
|
|
code := ORD("]")
|
|
ELSIF code = ORD("{") THEN
|
|
code := ORD("}")
|
|
ELSE
|
|
code := -1
|
|
END;
|
|
IF code # -1 THEN
|
|
Lines.insert(curLine, text.cursor.X + 1, WCHR(code))
|
|
END
|
|
END;
|
|
Lines.modify(curLine);
|
|
modify(text);
|
|
SetPos(text, text.cursor.X + 1, text.cursor.Y)
|
|
ELSIF code = 8 THEN
|
|
BkSpace(text)
|
|
ELSIF code = -8 THEN
|
|
IF selected(text) THEN
|
|
Indent(text, FALSE)
|
|
END
|
|
ELSIF code = 9 THEN
|
|
IF selected(text) THEN
|
|
Indent(text, TRUE)
|
|
ELSE
|
|
INC(text.smallChange);
|
|
tab(text)
|
|
END
|
|
ELSIF code = 13 THEN
|
|
enter(text)
|
|
END
|
|
END input;
|
|
|
|
|
|
PROCEDURE scroll* (text: tText; h, v: INTEGER);
|
|
BEGIN
|
|
INC(text.scroll.X, h);
|
|
INC(text.scroll.Y, v);
|
|
text.scroll.X := MIN(MAX(text.scroll.X, 0), text.maxLength);
|
|
text.scroll.Y := MIN(MAX(text.scroll.Y, 0), text.count - 1)
|
|
END scroll;
|
|
|
|
|
|
PROCEDURE save* (text: tText; name: RW.tFileName): BOOLEAN;
|
|
CONST
|
|
tempFile = "/tmp0/1/cedit~.tmp";
|
|
VAR
|
|
line: tLine;
|
|
file: RW.tOutput;
|
|
res: BOOLEAN;
|
|
Len: INTEGER;
|
|
BEGIN
|
|
ChangeLog.setGuard(text.edition);
|
|
file := RW.create(tempFile, text.enc, text.eol);
|
|
IF file # NIL THEN
|
|
ChangeLog.delSaved;
|
|
line := text.first(tLine);
|
|
WHILE line # NIL DO
|
|
IF trimSpace THEN
|
|
Len := Lines.trimLength(line)
|
|
ELSE
|
|
Len := line.length
|
|
END;
|
|
RW.putString(file, line, Len);
|
|
NextLine(line);
|
|
IF line # NIL THEN
|
|
RW.newLine(file)
|
|
END
|
|
END;
|
|
res := RW.close(file)
|
|
ELSE
|
|
res := FALSE
|
|
END;
|
|
IF res THEN
|
|
res := File.Copy(tempFile, name);
|
|
IF res THEN
|
|
text.modified := FALSE;
|
|
ChangeLog.save(text.edition);
|
|
|
|
line := text.first(tLine);
|
|
WHILE line # NIL DO
|
|
IF line.modified THEN
|
|
Lines.save(line)
|
|
END;
|
|
NextLine(line)
|
|
END
|
|
END
|
|
END;
|
|
IF File.Delete(tempFile) THEN END;
|
|
IF ~res THEN
|
|
ChangeLog.delCurSaved
|
|
END
|
|
RETURN res
|
|
END save;
|
|
|
|
|
|
PROCEDURE redoGuard (text: tText; guard: tGuard);
|
|
BEGIN
|
|
text.edition := guard;
|
|
text.cursor^ := guard.cursor;
|
|
text.select2^ := guard.select2;
|
|
text.scroll := guard.scroll;
|
|
text.CurX := guard.CurX;
|
|
IF guard.selected THEN
|
|
text.select := text.select2
|
|
ELSE
|
|
text.select := text.cursor
|
|
END;
|
|
text.curLine := getLine(text, text.cursor.Y);
|
|
text.comments := TRUE;
|
|
text.search := TRUE
|
|
END redoGuard;
|
|
|
|
|
|
PROCEDURE undo* (text: tText);
|
|
VAR
|
|
item: List.tItem;
|
|
guard: tGuard;
|
|
BEGIN
|
|
guard := text.edition;
|
|
item := guard.prev;
|
|
WHILE (item # NIL) & ~(item IS tGuard) DO
|
|
item := item.prev
|
|
END;
|
|
|
|
IF item # NIL THEN
|
|
guard := item(tGuard);
|
|
text.edition := guard
|
|
END;
|
|
|
|
item := ChangeLog.CL.Log.first;
|
|
WHILE item # guard DO
|
|
ChangeLog.redo(item);
|
|
item := item.next
|
|
END;
|
|
redoGuard(text, guard);
|
|
ChangeLog.setGuard(guard);
|
|
text.modified := ~guard.saved;
|
|
ShowCursor
|
|
END undo;
|
|
|
|
|
|
PROCEDURE redo* (text: tText);
|
|
VAR
|
|
item: List.tItem;
|
|
guard: tGuard;
|
|
BEGIN
|
|
guard := text.edition;
|
|
item := guard.next;
|
|
WHILE (item # NIL) & ~(item IS tGuard) DO
|
|
ChangeLog.redo(item);
|
|
item := item.next
|
|
END;
|
|
IF item # NIL THEN
|
|
guard := item(tGuard);
|
|
redoGuard(text, guard)
|
|
END;
|
|
ChangeLog.setGuard(guard);
|
|
text.modified := ~guard.saved;
|
|
ShowCursor
|
|
END redo;
|
|
|
|
|
|
PROCEDURE getSelCnt* (text: tText; VAR chars, lines: INTEGER);
|
|
VAR
|
|
selBeg, selEnd: tPoint;
|
|
first, last, line: tLine;
|
|
|
|
PROCEDURE charCnt (line: tLine; first, last: INTEGER): INTEGER;
|
|
VAR
|
|
i, res: INTEGER;
|
|
BEGIN
|
|
res := 0;
|
|
FOR i := first TO last DO
|
|
IF Lines.getChar(line, i) # TAB1 THEN
|
|
INC(res)
|
|
END
|
|
END
|
|
RETURN res
|
|
END charCnt;
|
|
|
|
BEGIN
|
|
IF selected(text) THEN
|
|
getSelect(text, selBeg, selEnd);
|
|
first := getLine2(text, selBeg.Y);
|
|
last := getLine2(text, selEnd.Y);
|
|
lines := selEnd.Y - selBeg.Y + 1;
|
|
|
|
IF lines > 1 THEN
|
|
chars := charCnt(first, selBeg.X, first.length - 1) + charCnt(last, 0, selEnd.X - 1) + lenEOL;
|
|
line := first.next(tLine);
|
|
WHILE line # last DO
|
|
INC(chars, charCnt(line, 0, line.length - 1) + lenEOL);
|
|
NextLine(line)
|
|
END
|
|
ELSE
|
|
chars := charCnt(first, selBeg.X, selEnd.X - 1)
|
|
END
|
|
ELSE
|
|
chars := 0;
|
|
lines := 0
|
|
END
|
|
END getSelCnt;
|
|
|
|
|
|
PROCEDURE Copy (text: tText);
|
|
VAR
|
|
selStart, selEnd: tPoint;
|
|
buffer: CB.tBuffer;
|
|
BEGIN
|
|
getSelect(text, selStart, selEnd);
|
|
buffer := plain(text, selStart, selEnd, TRUE);
|
|
CB.eot(buffer);
|
|
CB.put(buffer);
|
|
CB.destroy(buffer)
|
|
END Copy;
|
|
|
|
|
|
PROCEDURE paste (text: tText);
|
|
VAR
|
|
line, newLine, curLine: tLine;
|
|
w: INTEGER;
|
|
cliptext: RW.tInput;
|
|
eol: BOOLEAN;
|
|
cursor: pPoint;
|
|
|
|
|
|
PROCEDURE lineWidth (line: tLine; pos: INTEGER): INTEGER;
|
|
VAR
|
|
i, res: INTEGER;
|
|
c: WCHAR;
|
|
BEGIN
|
|
res := pos;
|
|
i := 0;
|
|
REPEAT
|
|
c := Lines.getChar(line, i);
|
|
IF c = TAB THEN
|
|
INC(res, Lines.tab - res MOD Lines.tab)
|
|
ELSIF c # TAB1 THEN
|
|
INC(res)
|
|
END;
|
|
INC(i)
|
|
UNTIL c = 0X
|
|
RETURN res - pos - 1
|
|
END lineWidth;
|
|
|
|
|
|
BEGIN
|
|
line := Lines.create(TRUE);
|
|
cliptext := RW.clipboard();
|
|
delSelect(text);
|
|
cursor := text.cursor;
|
|
WHILE (cliptext # NIL) & (RW.getString(cliptext, line, Lines.tabs, eol) >= 0) DO
|
|
IF line.length > 0 THEN
|
|
w := lineWidth(line, cursor.X);
|
|
Lines.insert2(text.curLine, cursor.X, line);
|
|
Lines.modify(text.curLine);
|
|
modify(text);
|
|
SetPos(text, cursor.X + w, cursor.Y);
|
|
resetSelect(text)
|
|
END;
|
|
IF eol THEN
|
|
newLine := Lines.create(FALSE);
|
|
modify(text);
|
|
curLine := text.curLine;
|
|
IF cursor.X < curLine.length THEN
|
|
Lines.wrap(curLine, newLine, cursor.X);
|
|
Lines.modify(curLine)
|
|
END;
|
|
List._insert(text, curLine, newLine);
|
|
Lines.modify(newLine);
|
|
SetPos(text, 0, cursor.Y + 1);
|
|
resetSelect(text)
|
|
END;
|
|
Lines.destroy(line);
|
|
line := Lines.create(TRUE)
|
|
END;
|
|
SetPos(text, cursor.X, cursor.Y);
|
|
Lines.destroy(line);
|
|
RW.destroy(cliptext)
|
|
END paste;
|
|
|
|
|
|
PROCEDURE searchScroll (text: tText; n: INTEGER);
|
|
BEGIN
|
|
IF n - text.scroll.Y > textsize.Y - 1 THEN
|
|
text.scroll.Y := MAX(n - 2 * textsize.Y DIV 3, 0)
|
|
ELSIF n < text.scroll.Y THEN
|
|
text.scroll.Y := MAX(n - textsize.Y DIV 3, 0)
|
|
END
|
|
END searchScroll;
|
|
|
|
|
|
PROCEDURE goto* (text: tText; n: INTEGER): BOOLEAN;
|
|
VAR
|
|
res: BOOLEAN;
|
|
BEGIN
|
|
DEC(n);
|
|
IF (0 <= n) & (n < text.count) THEN
|
|
resetSelect(text);
|
|
searchScroll(text, n);
|
|
SetPos(text, 0, n);
|
|
res := TRUE
|
|
ELSE
|
|
res := FALSE
|
|
END
|
|
RETURN res
|
|
END goto;
|
|
|
|
|
|
PROCEDURE toggleLabel* (text: tText);
|
|
BEGIN
|
|
text.curLine.label := ~text.curLine.label
|
|
END toggleLabel;
|
|
|
|
|
|
PROCEDURE gotoLabel* (text: tText; frw: BOOLEAN);
|
|
VAR
|
|
line: tLine;
|
|
n: INTEGER;
|
|
|
|
PROCEDURE search (VAR line: tLine; VAR n: INTEGER; frw: BOOLEAN);
|
|
BEGIN
|
|
IF frw THEN
|
|
WHILE (line # NIL) & ~line.label DO
|
|
NextLine(line);
|
|
INC(n)
|
|
END
|
|
ELSE
|
|
WHILE (line # NIL) & ~line.label DO
|
|
PrevLine(line);
|
|
DEC(n)
|
|
END
|
|
END
|
|
END search;
|
|
|
|
BEGIN
|
|
n := text.cursor.Y;
|
|
line := text.curLine;
|
|
IF frw THEN
|
|
NextLine(line);
|
|
INC(n)
|
|
ELSE
|
|
PrevLine(line);
|
|
DEC(n)
|
|
END;
|
|
search(line, n, frw);
|
|
IF line = NIL THEN
|
|
IF frw THEN
|
|
n := 0;
|
|
line := text.first(tLine)
|
|
ELSE
|
|
n := text.count - 1;
|
|
line := text.last(tLine)
|
|
END;
|
|
search(line, n, frw)
|
|
END;
|
|
IF line # NIL THEN
|
|
IF goto(text, n + 1) THEN END
|
|
END
|
|
END gotoLabel;
|
|
|
|
|
|
PROCEDURE changeCase (text: tText; upper: BOOLEAN);
|
|
VAR
|
|
i: INTEGER;
|
|
line: tLine;
|
|
func: Lines.fConvert;
|
|
BEGIN
|
|
line := text.curLine;
|
|
i := text.cursor.X - 1;
|
|
|
|
WHILE (i >= 0) & U.isLetter(Lines.getChar(line, i)) DO
|
|
DEC(i)
|
|
END;
|
|
|
|
IF upper THEN
|
|
func := U.upper
|
|
ELSE
|
|
func := U.lower
|
|
END;
|
|
|
|
IF Lines.convert(line, i + 1, text.cursor.X - 1, func) THEN
|
|
INC(text.smallChange);
|
|
modify(text)
|
|
END
|
|
END changeCase;
|
|
|
|
|
|
PROCEDURE chCase* (text: tText; upper: BOOLEAN);
|
|
VAR
|
|
selBeg, selEnd: tPoint;
|
|
first, line: Lines.tLine;
|
|
cnt: INTEGER;
|
|
func: Lines.fConvert;
|
|
modified: BOOLEAN;
|
|
BEGIN
|
|
modified := FALSE;
|
|
IF selected(text) THEN
|
|
getSelect(text, selBeg, selEnd);
|
|
first := getLine2(text, selBeg.Y);
|
|
line := first;
|
|
cnt := selEnd.Y - selBeg.Y;
|
|
|
|
IF upper THEN
|
|
func := U.upper
|
|
ELSE
|
|
func := U.lower
|
|
END;
|
|
|
|
IF cnt = 0 THEN
|
|
IF Lines.convert(line, selBeg.X, selEnd.X - 1, func) THEN
|
|
modified := TRUE
|
|
END
|
|
ELSE
|
|
IF Lines.convert(line, selBeg.X, line.length - 1, func) THEN
|
|
modified := TRUE
|
|
END;
|
|
WHILE cnt > 1 DO
|
|
NextLine(line);
|
|
IF Lines.convert(line, 0, line.length - 1, func) THEN
|
|
modified := TRUE
|
|
END;
|
|
DEC(cnt)
|
|
END;
|
|
NextLine(line);
|
|
IF Lines.convert(line, 0, selEnd.X - 1, func) THEN
|
|
modified := TRUE
|
|
END
|
|
END
|
|
END;
|
|
IF modified THEN
|
|
INC(text.smallChange);
|
|
modify(text)
|
|
END
|
|
END chCase;
|
|
|
|
|
|
PROCEDURE UpDown (text: tText; step: INTEGER);
|
|
VAR
|
|
temp: INTEGER;
|
|
BEGIN
|
|
IF text.CurX = -1 THEN
|
|
text.CurX := text.cursor.X
|
|
END;
|
|
temp := text.CurX;
|
|
SetPos(text, temp, text.cursor.Y + step);
|
|
text.CurX := temp
|
|
END UpDown;
|
|
|
|
|
|
PROCEDURE delLine* (text: tText);
|
|
BEGIN
|
|
text.smallChange := 2;
|
|
resetSelect(text);
|
|
IF text.curLine.length > 0 THEN
|
|
Lines.delCharN(text.curLine, 0, text.curLine.length)
|
|
END;
|
|
SetPos(text, 0, text.cursor.Y);
|
|
IF text.cursor.Y = text.count - 1 THEN
|
|
BkSpace(text)
|
|
ELSE
|
|
delete(text)
|
|
END
|
|
END delLine;
|
|
|
|
|
|
PROCEDURE dupLine* (text: tText);
|
|
VAR
|
|
newLine, curLine: tLine;
|
|
BEGIN
|
|
curLine := text.curLine;
|
|
newLine := Lines.create(FALSE);
|
|
modify(text);
|
|
Lines.insert3(newLine, 0, curLine.length);
|
|
List._insert(text, curLine, newLine);
|
|
Lines.move(curLine, newLine);
|
|
Lines.modify(newLine)
|
|
END dupLine;
|
|
|
|
|
|
PROCEDURE MoveLines* (text: tText; down: BOOLEAN);
|
|
VAR
|
|
last, first, line: tLine;
|
|
selBeg, selEnd, temp: tPoint;
|
|
step: INTEGER;
|
|
frw: BOOLEAN;
|
|
BEGIN
|
|
getSelect(text, selBeg, selEnd);
|
|
IF ((selBeg.Y > 0) & ~down OR (selEnd.Y < text.count - 1) & down) THEN
|
|
modify(text);
|
|
step := ORD(down)*2 - 1;
|
|
IF selBeg.Y # selEnd.Y THEN
|
|
frw := (text.cursor.X = selEnd.X) & (text.cursor.Y = selEnd.Y);
|
|
|
|
IF down # frw THEN
|
|
temp := text.cursor^;
|
|
SetPos(text, 0, text.select.Y);
|
|
setSelect(text);
|
|
text.select^ := temp
|
|
END;
|
|
|
|
ASSERT(selBeg.Y < selEnd.Y);
|
|
|
|
first := getLine(text, selBeg.Y);
|
|
last := getLine(text, selEnd.Y);
|
|
|
|
line := first;
|
|
Lines.modify(line);
|
|
REPEAT
|
|
NextLine(line);
|
|
Lines.modify(line)
|
|
UNTIL line = last;
|
|
|
|
IF down THEN
|
|
text.curLine := last.prev(tLine)
|
|
ELSE
|
|
text.curLine := first.next(tLine)
|
|
END;
|
|
selBeg.X := 0;
|
|
selEnd.X := last.length;
|
|
IF down THEN
|
|
last := last.next(tLine);
|
|
List._delete(text, last);
|
|
List._insert(text, first.prev, last)
|
|
ELSE
|
|
first := first.prev(tLine);
|
|
List._delete(text, first);
|
|
List._insert(text, last, first)
|
|
END;
|
|
IF down THEN
|
|
temp := selBeg;
|
|
selBeg := selEnd;
|
|
selEnd := temp;
|
|
END;
|
|
SetPos(text, selBeg.X, selBeg.Y + step);
|
|
setSelect(text);
|
|
text.select.X := selEnd.X;
|
|
text.select.Y := selEnd.Y + step
|
|
ELSE
|
|
first := getLine(text, selBeg.Y);
|
|
Lines.modify(first);
|
|
IF down THEN
|
|
last := first.next(tLine)
|
|
ELSE
|
|
last := first.prev.prev(tLine)
|
|
END;
|
|
List._delete(text, first);
|
|
List._insert(text, last, first);
|
|
INC(text.cursor.Y, step);
|
|
INC(text.select.Y, step);
|
|
SetPos(text, text.cursor.X, text.cursor.Y)
|
|
END
|
|
END
|
|
END MoveLines;
|
|
|
|
|
|
PROCEDURE getSelectedText* (text: tText; VAR s: ARRAY OF WCHAR);
|
|
VAR
|
|
n: INTEGER;
|
|
selBeg, selEnd: tPoint;
|
|
BEGIN
|
|
s[0] := 0X;
|
|
IF selected(text) & (text.cursor.Y = text.select.Y) THEN
|
|
getSelect(text, selBeg, selEnd);
|
|
n := getString(text.curLine, selBeg.X, selEnd.X - selBeg.X, s)
|
|
END
|
|
END getSelectedText;
|
|
|
|
|
|
PROCEDURE wordSel* (text: tText);
|
|
VAR
|
|
n, i, x1, x2: INTEGER;
|
|
selBeg, selEnd: tPoint;
|
|
str: tString;
|
|
curLine: tLine;
|
|
BEGIN
|
|
IF text.wordSel THEN
|
|
curLine := text.curLine;
|
|
IF selected(text) & (text.cursor.Y = text.select.Y) THEN
|
|
getSelect(text, selBeg, selEnd);
|
|
x1 := selBeg.X;
|
|
x2 := selEnd.X;
|
|
n := getString(curLine, x1, x2 - x1, str);
|
|
ELSE
|
|
str := ""
|
|
END;
|
|
IF str # "" THEN
|
|
i := 0;
|
|
WHILE (i < n) & U.isWordChar(str[i]) DO
|
|
INC(i)
|
|
END;
|
|
IF (i # n) OR
|
|
((x1 > 0) & U.isWordChar(Lines.getChar(curLine, x1 - 1))) OR
|
|
((x2 < curLine.length) & U.isWordChar(Lines.getChar(curLine, x2))) THEN
|
|
str := ""
|
|
END
|
|
END;
|
|
IF text.searchText # str THEN
|
|
text.smallMove := FALSE
|
|
END;
|
|
IF search(text, str, Lang.isCS(text.lang), TRUE) THEN END;
|
|
text.wordSel := FALSE
|
|
END;
|
|
(*IF (text.lang = Lang.langFasm) & ~selected(text) THEN
|
|
fasm_anon(text)
|
|
END*)
|
|
END wordSel;
|
|
|
|
|
|
PROCEDURE getWordPos (line: tLine; pos: INTEGER): INTEGER;
|
|
VAR
|
|
c: WCHAR;
|
|
BEGIN
|
|
c := Lines.getChar(line, pos);
|
|
IF U.isWordChar(c) THEN
|
|
WHILE (pos < line.length) & U.isWordChar(Lines.getChar(line, pos)) DO
|
|
INC(pos)
|
|
END
|
|
ELSIF Lines.isSpace(c) THEN
|
|
WHILE (pos < line.length) & Lines.isSpace(Lines.getChar(line, pos)) DO
|
|
INC(pos)
|
|
END
|
|
ELSE
|
|
WHILE (pos < line.length) & ~Lines.isSpace(Lines.getChar(line, pos)) & ~U.isWordChar(Lines.getChar(line, pos)) DO
|
|
INC(pos)
|
|
END
|
|
END
|
|
RETURN pos
|
|
END getWordPos;
|
|
|
|
|
|
PROCEDURE key* (text: tText; code: INTEGER; shift, ctrl: BOOLEAN);
|
|
VAR
|
|
n, wPos: INTEGER;
|
|
scrX, scrY: INTEGER;
|
|
resSel: BOOLEAN;
|
|
BEGIN
|
|
resSel := FALSE;
|
|
IF shift THEN
|
|
setSelect(text)
|
|
ELSE
|
|
IF (33 <= code) & (code <= 40) THEN
|
|
IF ~(((code = 38) OR (code = 40)) & ctrl) THEN
|
|
resSel := selected(text);
|
|
resetSelect(text)
|
|
END
|
|
END
|
|
END;
|
|
|
|
CASE code OF
|
|
|33:
|
|
IF ctrl THEN
|
|
UpDown(text, text.scroll.Y - text.cursor.Y)
|
|
ELSE
|
|
text.scroll.Y := MAX(text.scroll.Y - textsize.Y, 0);
|
|
UpDown(text, -textsize.Y)
|
|
END
|
|
|34:
|
|
IF ctrl THEN
|
|
UpDown(text, MIN(text.scroll.Y + textsize.Y - 1, text.count - 1) - text.cursor.Y)
|
|
ELSE
|
|
text.scroll.Y := MIN(text.scroll.Y + textsize.Y, text.count - 1);
|
|
UpDown(text, textsize.Y)
|
|
END
|
|
|35:
|
|
IF ctrl THEN
|
|
SetPos(text, text.last(tLine).length, text.count - 1)
|
|
ELSE
|
|
SetPos(text, text.curLine.length, text.cursor.Y)
|
|
END
|
|
|36:
|
|
IF ctrl THEN
|
|
SetPos(text, 0, 0)
|
|
ELSE
|
|
n := leadingSpaces(text.curLine);
|
|
IF text.cursor.X <= n THEN
|
|
n := 0
|
|
END;
|
|
SetPos(text, n, text.cursor.Y)
|
|
END
|
|
|37:
|
|
IF (text.cursor.X = 0) & (text.curLine.prev # NIL) THEN
|
|
SetPos(text, text.curLine.prev(tLine).length, text.cursor.Y - 1)
|
|
ELSE
|
|
scrX := text.scroll.X;
|
|
scrY := text.scroll.Y;
|
|
IF ctrl THEN
|
|
wPos := 0;
|
|
REPEAT
|
|
n := wPos;
|
|
wPos := getWordPos(text.curLine, wPos)
|
|
UNTIL wPos >= text.cursor.X;
|
|
move(text, n - text.cursor.X)
|
|
ELSE
|
|
move(text, -1)
|
|
END;
|
|
text.smallMove := (scrX = text.scroll.X) & (scrY = text.scroll.Y) & ~resSel
|
|
END
|
|
|38:
|
|
IF ctrl THEN
|
|
MoveLines(text, FALSE)
|
|
ELSE
|
|
UpDown(text, -1)
|
|
END
|
|
|39:
|
|
IF (text.cursor.X = text.curLine.length) & (text.curLine.next # NIL) THEN
|
|
SetPos(text, 0, text.cursor.Y + 1)
|
|
ELSE
|
|
scrX := text.scroll.X;
|
|
scrY := text.scroll.Y;
|
|
IF ctrl THEN
|
|
move(text, getWordPos(text.curLine, text.cursor.X) - text.cursor.X)
|
|
ELSE
|
|
move(text, 1)
|
|
END;
|
|
text.smallMove := (scrX = text.scroll.X) & (scrY = text.scroll.Y) & ~resSel
|
|
END
|
|
|40:
|
|
IF ctrl THEN
|
|
MoveLines(text, TRUE)
|
|
ELSE
|
|
UpDown(text, 1)
|
|
END
|
|
|46:
|
|
IF ctrl THEN
|
|
delLine(text)
|
|
ELSE
|
|
IF ~selected(text) & (text.cursor.X < text.curLine.length) THEN
|
|
INC(text.smallChange)
|
|
END;
|
|
delete(text);
|
|
ShowCursor
|
|
END
|
|
|ORD("C"), ORD("X"):
|
|
IF ctrl THEN
|
|
IF selected(text) THEN
|
|
Copy(text);
|
|
IF code = ORD("X") THEN
|
|
delSelect(text)
|
|
END
|
|
END
|
|
END
|
|
|ORD("V"):
|
|
IF ctrl THEN
|
|
IF CB.available() THEN
|
|
paste(text)
|
|
END
|
|
END
|
|
|ORD("A"):
|
|
IF ctrl THEN
|
|
text.select2.X := 0;
|
|
text.select2.Y := 0;
|
|
text.select := text.select2;
|
|
SetPos(text, text.last(tLine).length, text.count - 1)
|
|
END
|
|
|ORD("L"), ORD("U"):
|
|
IF ctrl THEN
|
|
IF selected(text) THEN
|
|
chCase(text, code = ORD("U"))
|
|
ELSE
|
|
changeCase(text, code = ORD("U"))
|
|
END;
|
|
ShowCursor
|
|
END
|
|
|ORD("D"):
|
|
IF ctrl THEN
|
|
dupLine(text)
|
|
END
|
|
ELSE
|
|
END
|
|
END key;
|
|
|
|
|
|
PROCEDURE mouse* (text: tText; x, y: INTEGER);
|
|
VAR
|
|
cursorX: INTEGER;
|
|
BEGIN
|
|
DEC(x, padding.left);
|
|
DEC(y, padding.top);
|
|
cursorX := (x*2) DIV charWidth;
|
|
SetPos(text, cursorX DIV 2 + cursorX MOD 2 + text.scroll.X, y DIV charHeight + text.scroll.Y)
|
|
END mouse;
|
|
|
|
|
|
PROCEDURE selectWord* (text: tText);
|
|
VAR
|
|
cursorX, x1, x2: INTEGER;
|
|
line: tLine;
|
|
BEGIN
|
|
resetSelect(text);
|
|
cursorX := text.cursor.X;
|
|
line := text.curLine;
|
|
x1 := cursorX - 1;
|
|
IF (cursorX < line.length) & U.isWordChar(Lines.getChar(line, cursorX)) THEN
|
|
x2 := cursorX;
|
|
WHILE (x2 < line.length) & U.isWordChar(Lines.getChar(line, x2)) DO
|
|
INC(x2)
|
|
END
|
|
ELSE
|
|
WHILE (x1 >= 0) & ~U.isWordChar(Lines.getChar(line, x1)) DO
|
|
DEC(x1)
|
|
END;
|
|
x2 := x1 + 1
|
|
END;
|
|
WHILE (x1 >= 0) & U.isWordChar(Lines.getChar(line, x1)) DO
|
|
DEC(x1)
|
|
END;
|
|
INC(x1);
|
|
IF x1 < x2 THEN
|
|
SetPos(text, x1, text.cursor.Y);
|
|
setSelect(text);
|
|
SetPos(text, x2, text.cursor.Y)
|
|
END
|
|
END selectWord;
|
|
|
|
|
|
PROCEDURE cursor* (text: tText);
|
|
VAR
|
|
x, y1, y2, scrollX, scrollY: INTEGER;
|
|
cursor: pPoint;
|
|
BEGIN
|
|
IF drawCursor THEN
|
|
cursor := text.cursor;
|
|
scrollX := text.scroll.X;
|
|
scrollY := text.scroll.Y;
|
|
IF ~((scrollY > cursor.Y) OR (scrollY + textsize.Y + 1 <= cursor.Y) OR
|
|
(scrollX > cursor.X) OR (scrollX + textsize.X <= cursor.X)) THEN
|
|
x := (cursor.X - scrollX)*charWidth + padding.left;
|
|
y1 := (cursor.Y - scrollY)*charHeight + padding.top + (LineSpacing DIV 2 + 1);
|
|
y2 := y1 + charHeight - (LineSpacing + 2);
|
|
G.notVLine(canvas, x, y1, y2);
|
|
G.notVLine(canvas, x - 1, y1, y2)
|
|
END
|
|
END
|
|
END cursor;
|
|
|
|
|
|
PROCEDURE drawSelect (text: tText; line: tLine; selBeg, selEnd, y: INTEGER);
|
|
VAR
|
|
Len, pos, x, firstCharIdx: INTEGER;
|
|
BEGIN
|
|
firstCharIdx := MAX(text.scroll.X, selBeg);
|
|
Len := MAX(MIN(line.length - firstCharIdx, selEnd - firstCharIdx), 0);
|
|
Len := MIN(Len, textsize.X - pos + 1);
|
|
SetColor(colors.seltext, colors.selback);
|
|
pos := MAX((selBeg - text.scroll.X), 0);
|
|
x := pos*charWidth + padding.left;
|
|
G.SetColor(canvas, colors.selback);
|
|
G.FillRect(canvas, x - 1, y - LineSpacing DIV 2,
|
|
x + Len*charWidth, y - LineSpacing DIV 2 + charHeight);
|
|
G.TextOut(canvas, pos*charWidth + padding.left, y, Lines.getPChar(line, firstCharIdx), Len, colors.seltext)
|
|
END drawSelect;
|
|
|
|
|
|
PROCEDURE mark (line: tLine; y: INTEGER);
|
|
VAR
|
|
color, i: INTEGER;
|
|
BEGIN
|
|
IF line.modified THEN
|
|
color := colors.modified
|
|
ELSIF line.saved THEN
|
|
color := colors.saved
|
|
ELSE
|
|
color := colors.back
|
|
END;
|
|
G.SetColor(canvas, color);
|
|
|
|
FOR i := 3 TO mark_width + 2 DO
|
|
G.VLine(canvas, padding.left - i, y, y + charHeight)
|
|
END
|
|
END mark;
|
|
|
|
|
|
PROCEDURE setPadding (left, top: INTEGER);
|
|
BEGIN
|
|
padding.left := left;
|
|
padding.top := top;
|
|
textsize.X := (size.X - padding.left) DIV charWidth;
|
|
textsize.Y := (size.Y - padding.top) DIV charHeight;
|
|
END setPadding;
|
|
|
|
|
|
PROCEDURE draw* (text: tText);
|
|
VAR
|
|
y, n, cnt, i, x, pos: INTEGER;
|
|
line, firstLine, lastLine: tLine;
|
|
selBeg, selEnd: tPoint;
|
|
s: ARRAY 12 OF WCHAR;
|
|
backColor, numWidth, xNum, wNum: INTEGER;
|
|
guard: tGuard;
|
|
p: Search.tPos;
|
|
BEGIN
|
|
IF text.comments THEN
|
|
Comments(text)
|
|
END;
|
|
IF text.search & search(text, text.searchText, text.cs, text.whole) THEN END;
|
|
IF text.guard THEN
|
|
NEW(guard);
|
|
List.append(ChangeLog.CL.Log, guard);
|
|
guard.saved := ChangeLog.isFirstGuard(guard);
|
|
text.edition := guard;
|
|
text.guard := FALSE
|
|
ELSE
|
|
guard := text.edition
|
|
END;
|
|
|
|
guard.cursor := text.cursor^;
|
|
guard.select2 := text.select2^;
|
|
guard.scroll := text.scroll;
|
|
guard.CurX := text.CurX;
|
|
guard.selected := text.select = text.select2;
|
|
|
|
G.SetColor(canvas, colors.back);
|
|
IF ~text.smallMove THEN
|
|
G.clear(canvas)
|
|
END;
|
|
wNum := charWidth;
|
|
IF lineNumbers THEN
|
|
numWidth := U.lg10(text.count) + 2;
|
|
xNum := numWidth*wNum - wNum DIV 2;
|
|
setPadding(numWidth*wNum + pad_left, padding.top);
|
|
ELSE
|
|
setPadding(pad_left + wNum*2, padding.top)
|
|
END;
|
|
getSelect(text, selBeg, selEnd);
|
|
y := padding.top + LineSpacing DIV 2;
|
|
n := text.scroll.Y;
|
|
firstLine := getLine2(text, n);
|
|
|
|
IF text.smallMove THEN
|
|
line := text.curLine;
|
|
cnt := textsize.Y;
|
|
y := y + charHeight*(text.cursor.Y - text.scroll.Y);
|
|
G.SetColor(canvas, colors.back);
|
|
G.FillRect(canvas, padding.left - 2, y - LineSpacing DIV 2,
|
|
size.X - 1, y - LineSpacing DIV 2 + charHeight);
|
|
n := text.cursor.Y
|
|
ELSE
|
|
line := firstLine;
|
|
cnt := 0
|
|
END;
|
|
|
|
WHILE (line # NIL) & (cnt <= textsize.Y) DO
|
|
backColor := colors.back;
|
|
IF (line = text.curLine) & ~selected(text) THEN
|
|
G.SetColor(canvas, colors.curline);
|
|
G.FillRect(canvas, padding.left - 2, y - LineSpacing DIV 2,
|
|
size.X - 1, y - LineSpacing DIV 2 + charHeight);
|
|
backColor := colors.curline
|
|
END;
|
|
SetColor(colors.text, backColor);
|
|
IF (selBeg.Y < n) & (n < selEnd.Y) THEN
|
|
drawSelect(text, line, 0, line.length, y)
|
|
ELSE
|
|
G.TextOut(canvas, padding.left, y, Lines.getPChar(line, text.scroll.X), MIN(MAX(line.length - text.scroll.X, 0), textsize.X + 1), colors.delim);
|
|
IF text.lang # Lang.langText THEN
|
|
parse(text, line, y, backColor, text.lang)
|
|
END
|
|
END;
|
|
IF (selBeg.Y = n) & (selEnd.Y = n) & (selBeg.X # selEnd.X) THEN
|
|
drawSelect(text, line, selBeg.X, selEnd.X, y)
|
|
ELSIF (selBeg.Y = n) & (selEnd.Y # n) THEN
|
|
drawSelect(text, line, selBeg.X, line.length, y)
|
|
ELSIF (selBeg.Y # n) & (selEnd.Y = n) THEN
|
|
drawSelect(text, line, 0, selEnd.X, y)
|
|
END;
|
|
mark(line, y - LineSpacing DIV 2);
|
|
NextLine(line);
|
|
INC(y, charHeight);
|
|
INC(n);
|
|
INC(cnt)
|
|
END;
|
|
|
|
G.SetColor(canvas, colors.numback);
|
|
G.FillRect(canvas, 0, 0, padding.left - pad_left (*+ 1*), size.Y - 1);
|
|
line := firstLine;
|
|
SetColor(colors.numtext, colors.numback);
|
|
y := padding.top + LineSpacing DIV 2;
|
|
n := MIN(text.scroll.Y + textsize.Y + 1, text.count);
|
|
FOR i := text.scroll.Y + 1 TO n DO
|
|
IF lineNumbers THEN
|
|
IF (i MOD 10 = 0) OR (i - 1 = text.cursor.Y) OR line.label THEN
|
|
U.int2str(i, s);
|
|
G.TextOut2(canvas, (numWidth - U.lg10(i) - 1)*wNum - wNum DIV 2, y, s, LENGTH(s))
|
|
ELSE
|
|
G.SetColor(canvas, colors.numtext);
|
|
G.HLine(canvas, y - LineSpacing DIV 2 + charHeight DIV 2,
|
|
xNum - wNum DIV (1 + ORD(i MOD 5 # 0)), xNum)
|
|
END
|
|
END;
|
|
IF line.label THEN
|
|
FOR x := wNum DIV 2 TO (padding.left - pad_left) - wNum DIV 2 DO
|
|
G.notVLine(canvas, x, y, y + charHeight - (LineSpacing + 1));
|
|
G.xorVLine(canvas, x, y, y + charHeight - (LineSpacing + 1))
|
|
END
|
|
END;
|
|
NextLine(line);
|
|
INC(y, charHeight)
|
|
END;
|
|
|
|
IF text.searchText # "" THEN
|
|
IF text.smallMove THEN
|
|
firstLine := text.curLine;
|
|
lastLine := firstLine
|
|
ELSE
|
|
lastLine := getLine2(text, MIN(text.scroll.Y + textsize.Y + 1, text.count) - 1)
|
|
END;
|
|
|
|
i := 0;
|
|
p := text.foundList.first(Search.tPos);
|
|
pos := Search.next(p, i);
|
|
WHILE pos # -1 DO
|
|
y := padding.top + LineSpacing DIV 2;
|
|
IF text.smallMove THEN
|
|
y := y + charHeight*(text.cursor.Y - text.scroll.Y)
|
|
END;
|
|
IF (firstLine.pos <= pos) & (pos <= lastLine.pos + lastLine.length) THEN
|
|
line := firstLine;
|
|
WHILE (line.pos <= pos) & (line # lastLine) DO
|
|
NextLine(line);
|
|
INC(y, charHeight)
|
|
END;
|
|
IF (line # lastLine) & (line # firstLine) OR (line = lastLine) & (line.pos > pos) THEN
|
|
PrevLine(line);
|
|
DEC(y, charHeight)
|
|
END;
|
|
x := (pos - line.pos - text.scroll.X)*charWidth + padding.left;
|
|
n := LENGTH(text.searchText)*charWidth;
|
|
WHILE n > 0 DO
|
|
IF x >= padding.left THEN
|
|
G.notVLine(canvas, x, y, y + charHeight - LineSpacing)
|
|
END;
|
|
INC(x);
|
|
DEC(n)
|
|
END
|
|
END;
|
|
pos := Search.next(p, i)
|
|
END
|
|
END;
|
|
|
|
text.smallMove := FALSE;
|
|
|
|
IF text.foundSel > 0 THEN
|
|
x := (text.cursor.X - text.scroll.X)*charWidth + padding.left;
|
|
y := (text.cursor.Y - text.scroll.Y)*charHeight + padding.top + LineSpacing DIV 2;
|
|
n := text.foundSel*charWidth;
|
|
WHILE n > 0 DO
|
|
IF x >= padding.left THEN
|
|
G.xorVLine(canvas, x, y, y + charHeight - LineSpacing)
|
|
END;
|
|
INC(x);
|
|
DEC(n)
|
|
END
|
|
END;
|
|
cursor(text)
|
|
END draw;
|
|
|
|
|
|
PROCEDURE switch* (text: tText);
|
|
BEGIN
|
|
ChangeLog.setLog(text.chLog);
|
|
Lines.setMaxLength(text.maxLength);
|
|
Lang.setCurLang(text.lang)
|
|
END switch;
|
|
|
|
|
|
PROCEDURE create (fileName: RW.tFileName): tText;
|
|
VAR
|
|
text: tText;
|
|
BEGIN
|
|
NEW(text);
|
|
text.maxLength := 64;
|
|
text.chLog := ChangeLog.create(text.maxLength);
|
|
NEW(text.cursor);
|
|
NEW(text.select2);
|
|
text.cursor.X := 0;
|
|
text.cursor.Y := 0;
|
|
resetSelect(text);
|
|
text.scroll.X := 0;
|
|
text.scroll.Y := 0;
|
|
setPadding(padding.left, padding.top);
|
|
text.curLine := NIL;
|
|
text.modified := FALSE;
|
|
text.smallMove := FALSE;
|
|
text.comments := TRUE;
|
|
text.search := TRUE;
|
|
text.cs := FALSE;
|
|
text.whole := FALSE;
|
|
text.guard := TRUE;
|
|
text.wordSel := FALSE;
|
|
text.edition := NIL;
|
|
text.foundList := List.create(NIL);
|
|
text.searchText := "";
|
|
text.foundSel := 0;
|
|
text.CurX := -1;
|
|
text.smallChange := 0;
|
|
text.lang := Lang.langText;
|
|
text.LinesVector := NIL;
|
|
Lang.setCurLang(Lang.langText);
|
|
setName(text, fileName);
|
|
ASSERT(text = List.create(text))
|
|
RETURN text
|
|
END create;
|
|
|
|
|
|
PROCEDURE setColors* (text, back, seltext, selback, modified, saved, curline, numtext, numback,
|
|
comment, string, escape, num, delim, key1, key2, key3: INTEGER);
|
|
BEGIN
|
|
colors.text := text;
|
|
colors.back := back;
|
|
colors.seltext := seltext;
|
|
colors.selback := selback;
|
|
colors.modified := modified;
|
|
colors.saved := saved;
|
|
colors.curline := curline;
|
|
colors.numtext := numtext;
|
|
colors.numback := numback;
|
|
colors.comment := comment;
|
|
colors.string := string;
|
|
colors.escape := escape;
|
|
colors.num := num;
|
|
colors.delim := delim;
|
|
colors.key1 := key1;
|
|
colors.key2 := key2;
|
|
colors.key3 := key3;
|
|
END setColors;
|
|
|
|
|
|
PROCEDURE setCanvas* (_canvas: G.tCanvas);
|
|
BEGIN
|
|
canvas := _canvas;
|
|
charWidth := _canvas.font.width;
|
|
charHeight := _canvas.font.height + LineSpacing
|
|
END setCanvas;
|
|
|
|
|
|
PROCEDURE resize* (width, height: INTEGER);
|
|
BEGIN
|
|
size.X := width;
|
|
size.Y := height;
|
|
setPadding(padding.left, padding.top)
|
|
END resize;
|
|
|
|
|
|
PROCEDURE destroy* (VAR text: tText);
|
|
BEGIN
|
|
IF search(text, "", FALSE, FALSE) THEN END;
|
|
ChangeLog.destroy(text.chLog);
|
|
Lines.destroyVector(text.LinesVector);
|
|
DISPOSE(text.foundList);
|
|
DISPOSE(text.cursor);
|
|
DISPOSE(text.select2);
|
|
DISPOSE(text)
|
|
END destroy;
|
|
|
|
|
|
PROCEDURE open* (name: RW.tFileName; ptr, size: INTEGER; VAR errno: INTEGER): tText;
|
|
VAR
|
|
text: tText;
|
|
file: RW.tInput;
|
|
n, enc, eol: INTEGER;
|
|
_eol: BOOLEAN;
|
|
line: tLine;
|
|
BEGIN
|
|
errno := 0;
|
|
text := create(name);
|
|
IF text # NIL THEN
|
|
IF ptr = 0 THEN
|
|
file := RW.loadFromFile(name, enc, eol)
|
|
ELSE
|
|
file := RW.loadFromMem(ptr, size, enc, eol)
|
|
END;
|
|
IF file = NIL THEN
|
|
destroy(text)
|
|
END
|
|
ELSE
|
|
file := NIL
|
|
END;
|
|
IF file # NIL THEN
|
|
ChangeLog.changeInt(text.enc, enc);
|
|
ChangeLog.changeInt(text.eol, eol);
|
|
text.enc := enc;
|
|
text.eol := eol;
|
|
line := Lines.create(FALSE);
|
|
List._append(text, line);
|
|
REPEAT
|
|
n := RW.getString(file, line, Lines.tabs, _eol);
|
|
IF _eol THEN
|
|
line := Lines.create(FALSE);
|
|
List._append(text, line)
|
|
END
|
|
UNTIL ~_eol;
|
|
RW.destroy(file);
|
|
text.curLine := text.first(tLine);
|
|
SetPos(text, 0, 0);
|
|
resetSelect(text);
|
|
Comments(text)
|
|
ELSE
|
|
errno := 1
|
|
END
|
|
RETURN text
|
|
END open;
|
|
|
|
|
|
PROCEDURE findNext* (text: tText; prev: BOOLEAN): BOOLEAN;
|
|
VAR
|
|
cursorPos, x, y, X, Y, Len: INTEGER;
|
|
line: tLine;
|
|
res: BOOLEAN;
|
|
pos, i, pos0, first, last, num, cnt: INTEGER;
|
|
p: Search.tPos;
|
|
BEGIN
|
|
X := text.cursor.X;
|
|
Y := text.cursor.Y;
|
|
text.cursor.X := MIN(text.cursor.X, text.curLine.length);
|
|
cursorPos := text.curLine.pos + text.cursor.X - ORD(prev) - ORD(~prev & (text.foundSel = 0));
|
|
pos0 := -1;
|
|
|
|
cnt := 0;
|
|
IF text.foundList.count # 0 THEN
|
|
p := text.foundList.first(Search.tPos);
|
|
first := p.pos[0];
|
|
WHILE p # NIL DO
|
|
INC(cnt, p.cnt);
|
|
p := p.next(Search.tPos)
|
|
END;
|
|
p := text.foundList.last(Search.tPos);
|
|
last := p.pos[p.cnt - 1]
|
|
ELSE
|
|
first := -1;
|
|
last := -1
|
|
END;
|
|
text.foundCnt := cnt;
|
|
|
|
num := 1;
|
|
i := 0;
|
|
p := text.foundList.first(Search.tPos);
|
|
pos := Search.next(p, i);
|
|
WHILE (pos # -1) & (pos <= cursorPos) DO
|
|
pos0 := pos;
|
|
pos := Search.next(p, i);
|
|
INC(num)
|
|
END;
|
|
IF prev THEN
|
|
pos := pos0;
|
|
DEC(num)
|
|
END;
|
|
|
|
IF pos = -1 THEN
|
|
IF prev THEN
|
|
pos := last;
|
|
num := cnt
|
|
ELSE
|
|
pos := first;
|
|
num := 1
|
|
END
|
|
END;
|
|
|
|
res := pos # -1;
|
|
IF res THEN
|
|
y := 0;
|
|
line := text.first(tLine);
|
|
WHILE (line.pos <= pos) & (line.next # NIL) DO
|
|
NextLine(line);
|
|
INC(y)
|
|
END;
|
|
IF (line.next # NIL) OR (line.pos > pos) THEN
|
|
PrevLine(line);
|
|
DEC(y)
|
|
END;
|
|
resetSelect(text);
|
|
searchScroll(text, y);
|
|
x := pos - line.pos;
|
|
Len := LENGTH(text.searchText);
|
|
IF x + Len > text.scroll.X + textsize.X THEN
|
|
text.scroll.X := MAX(x + Len - textsize.X + 3, 0)
|
|
ELSIF x < text.scroll.X THEN
|
|
text.scroll.X := MAX(x - 3, 0)
|
|
END;
|
|
SetPos(text, x, y);
|
|
text.foundSel := Len;
|
|
text.foundCur := num
|
|
ELSE
|
|
SetPos(text, X, Y);
|
|
text.foundCur := 0
|
|
END
|
|
RETURN res
|
|
END findNext;
|
|
|
|
|
|
PROCEDURE replace* (text: tText; s: ARRAY OF WCHAR; n: INTEGER);
|
|
VAR
|
|
line: tLine;
|
|
sLen, i: INTEGER;
|
|
BEGIN
|
|
IF text.foundSel > 0 THEN
|
|
line := text.curLine;
|
|
sLen := LENGTH(s);
|
|
i := text.cursor.X;
|
|
IF sLen > n THEN
|
|
Lines.insert3(line, i, sLen - n)
|
|
ELSIF n > sLen THEN
|
|
Lines.delCharN(line, i, n - sLen)
|
|
ELSE (* n = sLen *)
|
|
Lines.copy(line)
|
|
END;
|
|
SetPos(text, i + sLen, text.cursor.Y);
|
|
WHILE sLen > 0 DO
|
|
DEC(sLen);
|
|
Lines.setChar(line, i + sLen, s[sLen])
|
|
END;
|
|
resetSelect(text);
|
|
Lines.modify(line);
|
|
modify(text)
|
|
END
|
|
END replace;
|
|
|
|
|
|
PROCEDURE replaceAll* (text: tText; s: ARRAY OF WCHAR; n: INTEGER): INTEGER;
|
|
VAR
|
|
line: tLine;
|
|
y, k, d, pos, y0, i, c: INTEGER;
|
|
p: Search.tPos;
|
|
BEGIN
|
|
resetSelect(text);
|
|
SetPos(text, 0, 0);
|
|
line := text.first(tLine);
|
|
y := 0;
|
|
y0 := -1;
|
|
k := 0;
|
|
d := LENGTH(s) - n;
|
|
c := 0;
|
|
i := 0;
|
|
p := text.foundList.first(Search.tPos);
|
|
pos := Search.next(p, i);
|
|
WHILE pos # -1 DO
|
|
WHILE (line.pos <= pos) & (line.next # NIL) DO
|
|
NextLine(line);
|
|
INC(y)
|
|
END;
|
|
IF (line.next # NIL) OR (line.pos > pos) THEN
|
|
PrevLine(line);
|
|
DEC(y)
|
|
END;
|
|
IF y = y0 THEN
|
|
INC(k, d)
|
|
ELSE
|
|
k := 0;
|
|
y0 := y
|
|
END;
|
|
SetPos(text, pos - line.pos + k, y);
|
|
text.foundSel := n;
|
|
replace(text, s, n);
|
|
INC(c);
|
|
pos := Search.next(p, i)
|
|
END
|
|
RETURN c
|
|
END replaceAll;
|
|
|
|
|
|
PROCEDURE conv (VAR c: WCHAR; cp: E.CP; enc: INTEGER): BOOLEAN;
|
|
VAR
|
|
code: INTEGER;
|
|
res: BOOLEAN;
|
|
BEGIN
|
|
res := FALSE;
|
|
IF (c # 0X) & (c # Lines.NUL) & (c # Lines.TAB1) THEN
|
|
code := E.UNI[ORD(c), enc];
|
|
IF (0 <= code) & (code <= 255) THEN
|
|
code := cp[code]
|
|
ELSE
|
|
code := ORD(c)
|
|
END;
|
|
IF code # ORD(c) THEN
|
|
c := WCHR(code);
|
|
res := TRUE
|
|
END
|
|
END
|
|
RETURN res
|
|
END conv;
|
|
|
|
|
|
PROCEDURE conv1251to866 (VAR c: WCHAR): BOOLEAN;
|
|
RETURN conv(c, E.cp866, E.CP1251)
|
|
END conv1251to866;
|
|
|
|
|
|
PROCEDURE conv866to1251 (VAR c: WCHAR): BOOLEAN;
|
|
RETURN conv(c, E.cp1251, E.CP866)
|
|
END conv866to1251;
|
|
|
|
|
|
PROCEDURE convert* (text: tText; (*cp: E.CP;*) enc: INTEGER);
|
|
VAR
|
|
line: tLine;
|
|
func: Lines.fConvert;
|
|
modified: BOOLEAN;
|
|
BEGIN
|
|
modified := FALSE;
|
|
line := text.first(tLine);
|
|
IF enc = E.CP866 THEN
|
|
func := conv866to1251
|
|
ELSIF enc = E.CP1251 THEN
|
|
func := conv1251to866
|
|
ELSE
|
|
line := NIL
|
|
END;
|
|
|
|
WHILE line # NIL DO
|
|
IF Lines.convert(line, 0, line.length - 1, func) THEN
|
|
modified := TRUE
|
|
END;
|
|
NextLine(line)
|
|
END;
|
|
|
|
IF modified THEN
|
|
modify(text)
|
|
END
|
|
END convert;
|
|
|
|
|
|
PROCEDURE New* (): tText;
|
|
VAR
|
|
text: tText;
|
|
BEGIN
|
|
text := create("");
|
|
List._append(text, Lines.create(FALSE));
|
|
text.curLine := text.first(tLine);
|
|
ChangeLog.changeInt(text.enc, E.CP866);
|
|
ChangeLog.changeInt(text.eol, E.EOL_CRLF);
|
|
text.enc := E.CP866;
|
|
text.eol := E.EOL_CRLF;
|
|
SetPos(text, 0, 0);
|
|
resetSelect(text);
|
|
Comments(text)
|
|
RETURN text
|
|
END New;
|
|
|
|
|
|
PROCEDURE empty* (text: tText): BOOLEAN;
|
|
RETURN (text.count = 1) & (text.curLine.length = 0)
|
|
END empty;
|
|
|
|
|
|
PROCEDURE setLineSpacing* (canvas: G.tCanvas; value: INTEGER);
|
|
BEGIN
|
|
IF (0 <= value) & (value <= MaxLineSpacing) THEN
|
|
LineSpacing := value;
|
|
setCanvas(canvas)
|
|
END
|
|
END setLineSpacing;
|
|
|
|
|
|
PROCEDURE init* (pShowCursor: tProcedure;
|
|
_lineNumbers, _autoIndents, _autoBrackets, _trimSpace: BOOLEAN; _lineSpacing: INTEGER);
|
|
BEGIN
|
|
ShowCursor := pShowCursor;
|
|
pdelete := delete;
|
|
drawCursor := TRUE;
|
|
lineNumbers := _lineNumbers;
|
|
autoIndents := _autoIndents;
|
|
autoBrackets := _autoBrackets;
|
|
trimSpace := _trimSpace;
|
|
padding.left := pad_left;
|
|
padding.top := pad_top;
|
|
LineSpacing := _lineSpacing
|
|
END init;
|
|
|
|
|
|
END Text. |