mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-02 00:32:30 +02:00
243 lines
7.8 KiB
ObjectPascal
243 lines
7.8 KiB
ObjectPascal
{-------------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
Alternatively, the contents of this file may be used under the terms of the
|
|
GNU General Public License Version 2 or later (the "GPL"), in which case
|
|
the provisions of the GPL are applicable instead of those above.
|
|
If you wish to allow use of your version of this file only under the terms
|
|
of the GPL and not to allow others to use your version of this file
|
|
under the MPL, indicate your decision by deleting the provisions above and
|
|
replace them with the notice and other provisions required by the GPL.
|
|
If you do not delete the provisions above, a recipient may use your version
|
|
of this file under either the MPL or the GPL.
|
|
|
|
-------------------------------------------------------------------------------}
|
|
unit SynEditTextBase;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LCLProc, SynEditTypes;
|
|
|
|
type
|
|
|
|
{ TSynEditStrings }
|
|
|
|
TSynEditStrings = class(TStrings)
|
|
protected
|
|
FTabWidth: integer;
|
|
FIsUtf8: Boolean;
|
|
function GetIsUtf8 : Boolean; virtual;
|
|
procedure SetIsUtf8(const AValue : Boolean); virtual;
|
|
function GetTabWidth : integer; virtual;
|
|
procedure SetTabWidth(const AValue : integer); virtual;
|
|
function GetFoldEndLevel(Index: integer): integer; virtual; abstract;
|
|
function GetFoldMinLevel(Index: integer): integer; virtual; abstract;
|
|
procedure SetFoldEndLevel(Index: integer; const AValue: integer); virtual; abstract;
|
|
procedure SetFoldMinLevel(Index: integer; const AValue: integer); virtual; abstract;
|
|
function GetRange(Index: integer): TSynEditRange; virtual; abstract;
|
|
procedure PutRange(Index: integer; ARange: TSynEditRange); virtual; abstract;
|
|
function GetExpandedString(Index: integer): string; virtual; abstract;
|
|
function GetLengthOfLongestLine: integer; virtual; abstract;
|
|
procedure SetTextStr(const Value: string); override;
|
|
public
|
|
constructor Create;
|
|
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
|
|
procedure InsertLines(Index, NumLines: integer); virtual; abstract;
|
|
procedure InsertStrings(Index: integer; NewStrings: TStrings); virtual; abstract;
|
|
procedure ClearRanges(ARange: TSynEditRange); virtual; abstract;
|
|
public
|
|
// Byte to Char
|
|
function LogicalToPhysicalPos(const p: TPoint): TPoint;
|
|
function LogicalToPhysicalCol(const Line: string;
|
|
LogicalPos: integer): integer;
|
|
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
|
LogicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
|
// Char to Byte
|
|
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
|
function PhysicalToLogicalCol(const Line: string;
|
|
PhysicalPos: integer): integer;
|
|
function PhysicalToLogicalCol(const Line: string;
|
|
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
|
public
|
|
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
|
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
|
property TabWidth: integer read GetTabWidth write SetTabWidth;
|
|
property IsUtf8: Boolean read GetIsUtf8 write SetIsUtf8;
|
|
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
|
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel
|
|
write SetFoldMinLevel;
|
|
property FoldEndLevel[Index: integer]: integer read GetFoldEndLevel
|
|
write SetFoldEndLevel;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
{ TSynEditStrings }
|
|
|
|
constructor TSynEditStrings.Create;
|
|
begin
|
|
inherited Create;
|
|
TabWidth := 8;
|
|
IsUtf8 := True;
|
|
end;
|
|
|
|
function TSynEditStrings.GetIsUtf8 : Boolean;
|
|
begin
|
|
Result := FIsUtf8;
|
|
end;
|
|
|
|
function TSynEditStrings.GetTabWidth : integer;
|
|
begin
|
|
Result := FTabWidth;
|
|
end;
|
|
|
|
procedure TSynEditStrings.SetIsUtf8(const AValue : Boolean);
|
|
begin
|
|
FIsUtf8 := AValue;
|
|
end;
|
|
|
|
procedure TSynEditStrings.SetTabWidth(const AValue : integer);
|
|
begin
|
|
FTabWidth := AValue;
|
|
end;
|
|
|
|
procedure TSynEditStrings.SetTextStr(const Value : string);
|
|
var
|
|
StartPos: Integer;
|
|
p: Integer;
|
|
Len: Integer;
|
|
sl: TStringList;
|
|
begin
|
|
BeginUpdate;
|
|
sl:=TStringList.Create;
|
|
try
|
|
Clear;
|
|
p:=1;
|
|
StartPos:=p;
|
|
Len:=length(Value);
|
|
while p<=Len do begin
|
|
if not (Value[p] in [#10,#13]) then begin
|
|
inc(p);
|
|
end else begin
|
|
sl.Add(copy(Value,StartPos,p-StartPos));
|
|
inc(p);
|
|
if (p<=Len) and (Value[p] in [#10,#13]) and (Value[p-1]<>Value[p]) then
|
|
inc(p);
|
|
StartPos:=p;
|
|
end;
|
|
end;
|
|
if StartPos<=Len then
|
|
sl.Add(copy(Value,StartPos,Len-StartPos+1));
|
|
AddStrings(sl);
|
|
finally
|
|
sl.Free;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TSynEditStrings.LogicalToPhysicalPos(const p : TPoint) : TPoint;
|
|
begin
|
|
Result := p;
|
|
if Result.Y - 1 < Count then
|
|
Result.X:=LogicalToPhysicalCol(self[Result.Y - 1],Result.X);
|
|
end;
|
|
|
|
function TSynEditStrings.LogicalToPhysicalCol(const Line : string; LogicalPos : integer) : integer;
|
|
begin
|
|
Result := LogicalToPhysicalCol(PChar(Pointer(Line)),length(Line),LogicalPos,1,1);
|
|
end;
|
|
|
|
function TSynEditStrings.LogicalToPhysicalCol(Line : PChar; LineLen : integer; LogicalPos, StartBytePos, StartPhysicalPos : integer) : integer;
|
|
var
|
|
BytePos, ByteLen: integer;
|
|
ScreenPos: integer;
|
|
begin
|
|
ByteLen := LineLen;
|
|
// map UTF8 and Tab chars
|
|
ScreenPos := StartPhysicalPos;
|
|
BytePos:= StartBytePos;
|
|
while BytePos<LogicalPos do begin
|
|
if (BytePos <= ByteLen) then begin
|
|
if Line[BytePos-1] = #9 then begin
|
|
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
|
inc(BytePos);
|
|
end else begin
|
|
inc(ScreenPos);
|
|
if IsUTF8 then
|
|
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
|
else
|
|
inc(BytePos);
|
|
end;
|
|
end else begin
|
|
// beyond end of line
|
|
inc(ScreenPos,LogicalPos-BytePos);
|
|
break;
|
|
end;
|
|
end;
|
|
if (BytePos>LogicalPos) and (ScreenPos>StartPhysicalPos) then
|
|
dec(ScreenPos);
|
|
Result := ScreenPos;
|
|
end;
|
|
|
|
function TSynEditStrings.PhysicalToLogicalPos(const p : TPoint) : TPoint;
|
|
begin
|
|
Result := p;
|
|
if (Result.Y>=1) and (Result.Y <= Count) then
|
|
Result.X:=PhysicalToLogicalCol(self[Result.Y - 1],Result.X,1,1);
|
|
end;
|
|
|
|
function TSynEditStrings.PhysicalToLogicalCol(const Line : string; PhysicalPos : integer) : integer;
|
|
begin
|
|
Result:=PhysicalToLogicalCol(Line,PhysicalPos,1,1);
|
|
end;
|
|
|
|
function TSynEditStrings.PhysicalToLogicalCol(const Line : string; PhysicalPos, StartBytePos, StartPhysicalPos : integer) : integer;
|
|
var
|
|
BytePos, ByteLen: integer;
|
|
ScreenPos: integer;
|
|
PLine: PChar;
|
|
begin
|
|
ByteLen := Length(Line);
|
|
ScreenPos := StartPhysicalPos;
|
|
BytePos := StartBytePos;
|
|
PLine := PChar(Line);
|
|
// map utf and tab chars
|
|
while ScreenPos < PhysicalPos do begin
|
|
if (BytePos <= ByteLen) then begin
|
|
if (PLine[BytePos-1] <> #9) then begin
|
|
inc(ScreenPos);
|
|
if IsUTF8 then
|
|
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
|
else
|
|
inc(BytePos);
|
|
end else begin
|
|
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
|
inc(BytePos);
|
|
end;
|
|
end else begin
|
|
// beyond end of line
|
|
inc(BytePos,PhysicalPos-ScreenPos);
|
|
break;
|
|
end;
|
|
end;
|
|
if (ScreenPos>PhysicalPos) and (BytePos>1) and (BytePos-2<ByteLen)
|
|
and (PLine[BytePos-2]=#9) then
|
|
dec(BytePos);
|
|
Result := BytePos;
|
|
end;
|
|
|
|
end.
|
|
|