mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-13 00:08:13 +02:00
SynEdit Refactor: Move Selection to it's own class. (Also fixes insert into *empty* buffer, which did skip the 2nd last line / Fixes undo/paste of line-mode selection)
git-svn-id: trunk@17713 -
This commit is contained in:
parent
ebe1b9d29a
commit
6c76be7c59
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1406,6 +1406,7 @@ components/synedit/syneditmarkupspecialline.pp svneol=native#text/plain
|
|||||||
components/synedit/syneditmiscclasses.pp svneol=native#text/pascal
|
components/synedit/syneditmiscclasses.pp svneol=native#text/pascal
|
||||||
components/synedit/syneditmiscprocs.pp svneol=native#text/pascal
|
components/synedit/syneditmiscprocs.pp svneol=native#text/pascal
|
||||||
components/synedit/syneditplugins.pas svneol=native#text/pascal
|
components/synedit/syneditplugins.pas svneol=native#text/pascal
|
||||||
|
components/synedit/syneditpointclasses.pas svneol=native#text/plain
|
||||||
components/synedit/syneditregexsearch.pas svneol=native#text/pascal
|
components/synedit/syneditregexsearch.pas svneol=native#text/pascal
|
||||||
components/synedit/syneditsearch.pp svneol=native#text/pascal
|
components/synedit/syneditsearch.pp svneol=native#text/pascal
|
||||||
components/synedit/syneditstrconst.pp svneol=native#text/pascal
|
components/synedit/syneditstrconst.pp svneol=native#text/pascal
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,8 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
LCLProc,
|
LCLProc,
|
||||||
Classes, SysUtils, SynEditTypes, SynEditTextBuffer, SynEditTextBase, SynEditMiscClasses;
|
Classes, SysUtils, SynEditTypes, SynEditTextBuffer, SynEditTextBase,
|
||||||
|
SynEditMiscClasses, SynEditPointClasses;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
@ -191,27 +191,6 @@ type
|
|||||||
property Options: TSynSearchOptions write SetOptions;
|
property Options: TSynSearchOptions write SetOptions;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSynEditCaret }
|
|
||||||
|
|
||||||
TSynEditCaret = class
|
|
||||||
fLinePos : Integer; // 1 based
|
|
||||||
fCharPos : Integer; // 1 based
|
|
||||||
fOnChangeList : TMethodList;
|
|
||||||
private
|
|
||||||
function GetLineCharPos : TPoint;
|
|
||||||
procedure SetLineCharPos(const AValue : TPoint);
|
|
||||||
procedure setCharPos(const AValue : Integer);
|
|
||||||
procedure setLinePos(const AValue : Integer);
|
|
||||||
public
|
|
||||||
constructor Create;
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure AddChangeHandler(AHandler: TNotifyEvent);
|
|
||||||
procedure RemoveChangeHandler(AHandler: TNotifyEvent);
|
|
||||||
property LinePos : Integer read fLinePos write setLinePos;
|
|
||||||
property CharPos : Integer read fCharPos write setCharPos;
|
|
||||||
property LineCharPos : TPoint read GetLineCharPos write SetLineCharPos;
|
|
||||||
end;
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -552,57 +531,5 @@ begin
|
|||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{ TSynEditCaret }
|
|
||||||
|
|
||||||
function TSynEditCaret.GetLineCharPos : TPoint;
|
|
||||||
begin
|
|
||||||
Result := Point(fCharPos, fLinePos);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TSynEditCaret.SetLineCharPos(const AValue : TPoint);
|
|
||||||
begin
|
|
||||||
if (fCharPos = AValue.X) and (fLinePos = AValue.Y) then exit;
|
|
||||||
fCharPos:= AValue.X;
|
|
||||||
fLinePos:= AValue.Y;
|
|
||||||
fOnChangeList.CallNotifyEvents(self);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TSynEditCaret.setCharPos(const AValue : Integer);
|
|
||||||
begin
|
|
||||||
if fCharPos = AValue then exit;
|
|
||||||
fCharPos:= AValue;
|
|
||||||
fOnChangeList.CallNotifyEvents(self);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TSynEditCaret.setLinePos(const AValue : Integer);
|
|
||||||
begin
|
|
||||||
if fLinePos = AValue then exit;
|
|
||||||
fLinePos:= AValue;
|
|
||||||
fOnChangeList.CallNotifyEvents(self);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TSynEditCaret.Create;
|
|
||||||
begin
|
|
||||||
fOnChangeList := TMethodList.Create;
|
|
||||||
fLinePos:= 1;
|
|
||||||
fCharPos:= 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TSynEditCaret.Destroy;
|
|
||||||
begin
|
|
||||||
FreeAndNil(fOnChangeList);
|
|
||||||
inherited Destroy;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TSynEditCaret.AddChangeHandler(AHandler : TNotifyEvent);
|
|
||||||
begin
|
|
||||||
fOnChangeList.Add(TMethod(AHandler));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TSynEditCaret.RemoveChangeHandler(AHandler : TNotifyEvent);
|
|
||||||
begin
|
|
||||||
fOnChangeList.Remove(TMethod(AHandler));
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -131,6 +131,9 @@ function DecodeString(s: string): string;
|
|||||||
function fsNot (s : TFontStyles) : TFontStyles; inline;
|
function fsNot (s : TFontStyles) : TFontStyles; inline;
|
||||||
function fsXor (s1,s2 : TFontStyles) : TFontStyles; inline;
|
function fsXor (s1,s2 : TFontStyles) : TFontStyles; inline;
|
||||||
|
|
||||||
|
function CreateTabsAndSpaces(StartPos, SpaceLen, TabWidth: integer;
|
||||||
|
UseTabs: boolean): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -763,5 +766,33 @@ end; { DecodeString }
|
|||||||
{$IFDEF RestoreRangeChecking}{$R+}{$ENDIF}
|
{$IFDEF RestoreRangeChecking}{$R+}{$ENDIF}
|
||||||
{end} //gp 2000-06-24
|
{end} //gp 2000-06-24
|
||||||
|
|
||||||
|
function CreateTabsAndSpaces(StartPos, SpaceLen, TabWidth: integer;
|
||||||
|
UseTabs: boolean): string;
|
||||||
|
var
|
||||||
|
TabCount: Integer;
|
||||||
|
EndPos: Integer;
|
||||||
|
PosPlusOneTab: Integer;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
if not UseTabs then begin
|
||||||
|
Result:=StringOfChar(' ',SpaceLen);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
TabCount:=0;
|
||||||
|
EndPos:=StartPos+SpaceLen;
|
||||||
|
while StartPos<EndPos do begin
|
||||||
|
PosPlusOneTab:=StartPos+TabWidth-((StartPos-1) mod TabWidth);
|
||||||
|
if PosPlusOneTab<=EndPos then begin
|
||||||
|
inc(TabCount);
|
||||||
|
StartPos:=PosPlusOneTab;
|
||||||
|
end else begin
|
||||||
|
Result:=StringOfChar(' ',EndPos-StartPos);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if TabCount>0 then
|
||||||
|
Result:=StringOfChar(#9,TabCount)+Result;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
897
components/synedit/syneditpointclasses.pas
Normal file
897
components/synedit/syneditpointclasses.pas
Normal file
@ -0,0 +1,897 @@
|
|||||||
|
{-------------------------------------------------------------------------------
|
||||||
|
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 SynEditPointClasses;
|
||||||
|
|
||||||
|
{$I synedit.inc}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, LCLProc,
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
Imm,
|
||||||
|
{$ENDIF}
|
||||||
|
SynEditTextBase, SynEditTypes, SynEditMiscProcs, SynEditTextBuffer;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TInvalidateLines = procedure(FirstLine, LastLine: integer) of Object;
|
||||||
|
TLinesCountChanged = procedure (FirstLine, Count: integer) of Object;
|
||||||
|
|
||||||
|
{ TSynEditPointBase }
|
||||||
|
|
||||||
|
TSynEditPointBase = class
|
||||||
|
protected
|
||||||
|
FLines: TSynEditStrings;
|
||||||
|
FOnChangeList: TMethodList;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
constructor Create(Lines: TSynEditStrings);
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure AddChangeHandler(AHandler: TNotifyEvent);
|
||||||
|
procedure RemoveChangeHandler(AHandler: TNotifyEvent);
|
||||||
|
property Lines: TSynEditStrings read FLines write FLines;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TSynEditCaret = class;
|
||||||
|
|
||||||
|
{ TSynEditSelection }
|
||||||
|
|
||||||
|
TSynEditSelection = class(TSynEditPointBase)
|
||||||
|
FCaret: TSynEditCaret;
|
||||||
|
fUndoList: TSynEditUndoList;
|
||||||
|
FInvalidateLinesMethod: TInvalidateLines;
|
||||||
|
FLinesDeletedMethod: TLinesCountChanged;
|
||||||
|
FLinesInsertedMethod: TLinesCountChanged;
|
||||||
|
FEnabled: Boolean;
|
||||||
|
FSpacesToTabs: Boolean;
|
||||||
|
FSelectionMode: TSynSelectionMode;
|
||||||
|
FStartLinePos: Integer; // 1 based
|
||||||
|
FStartBytePos: Integer; // 1 based
|
||||||
|
FEndLinePos: Integer; // 1 based
|
||||||
|
FEndBytePos: Integer; // 1 based
|
||||||
|
private
|
||||||
|
function AdjustBytePosToCharacterStart(Line: integer; BytePos: integer): integer;
|
||||||
|
function GetFirstLineBytePos: TPoint;
|
||||||
|
function GetLastLineBytePos: TPoint;
|
||||||
|
procedure SetEnabled(const Value : Boolean);
|
||||||
|
procedure SetSelectionMode(const Value: TSynSelectionMode);
|
||||||
|
function GetStartLineBytePos: TPoint;
|
||||||
|
procedure SetStartLineBytePos(Value: TPoint);
|
||||||
|
function GetEndLineBytePos: TPoint;
|
||||||
|
procedure SetEndLineBytePos(Value: TPoint);
|
||||||
|
function GetSelText: string;
|
||||||
|
procedure SetSelText(const Value: string);
|
||||||
|
public
|
||||||
|
FMaxLeftChar: Integer;
|
||||||
|
constructor Create(ALines: TSynEditStrings);
|
||||||
|
//destructor Destroy; override;
|
||||||
|
procedure SetSelTextPrimitive(PasteMode: TSynSelectionMode; Value: PChar;
|
||||||
|
ATag: PInteger);
|
||||||
|
function SelAvail: Boolean;
|
||||||
|
function IsBackwardSel: Boolean; // SelStart < SelEnd ?
|
||||||
|
property Enabled: Boolean read FEnabled write SetEnabled;
|
||||||
|
property SpacesToTabs: Boolean read FSpacesToTabs write FSpacesToTabs;
|
||||||
|
property SelectionMode: TSynSelectionMode
|
||||||
|
read FSelectionMode write SetSelectionMode;
|
||||||
|
property SelText: String read GetSelText write SetSelText;
|
||||||
|
property StartLineBytePos: TPoint
|
||||||
|
read GetStartLineBytePos write SetStartLineBytePos;
|
||||||
|
property EndLineBytePos: TPoint
|
||||||
|
read GetEndLineBytePos write SetEndLineBytePos;
|
||||||
|
property StartLinePos: Integer read FStartLinePos;
|
||||||
|
property EndLinePos: Integer read FEndLinePos;
|
||||||
|
property StartBytePos: Integer read FStartBytePos;
|
||||||
|
property EndBytePos: Integer read FEndBytePos;
|
||||||
|
// Bounds ordered
|
||||||
|
property FirstLineBytePos: TPoint read GetFirstLineBytePos;
|
||||||
|
property LastLineBytePos: TPoint read GetLastLineBytePos;
|
||||||
|
property InvalidateLinesMethod : TInvalidateLines write FInvalidateLinesMethod;
|
||||||
|
property LinesDeletedMethod: TLinesCountChanged write FLinesDeletedMethod;
|
||||||
|
property LinesInsertedMethod: TLinesCountChanged write FLinesInsertedMethod;
|
||||||
|
property Caret: TSynEditCaret read FCaret write FCaret;
|
||||||
|
property UndoList: TSynEditUndoList read fUndoList write fUndoList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSynEditCaret }
|
||||||
|
|
||||||
|
TSynEditCaret = class(TSynEditPointBase)
|
||||||
|
fLinePos: Integer; // 1 based
|
||||||
|
fCharPos: Integer; // 1 based
|
||||||
|
private
|
||||||
|
function GetLineCharPos: TPoint;
|
||||||
|
function GetLineText : string;
|
||||||
|
procedure SetLineCharPos(const AValue: TPoint);
|
||||||
|
procedure setCharPos(const AValue: Integer);
|
||||||
|
procedure setLinePos(const AValue: Integer);
|
||||||
|
procedure SetLineText(const AValue : string);
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
property LinePos : Integer read fLinePos write setLinePos;
|
||||||
|
property CharPos : Integer read fCharPos write setCharPos;
|
||||||
|
property LineCharPos : TPoint read GetLineCharPos write SetLineCharPos;
|
||||||
|
property LineText: string read GetLineText write SetLineText;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TSynEditPointBase }
|
||||||
|
|
||||||
|
constructor TSynEditPointBase.Create;
|
||||||
|
begin
|
||||||
|
FOnChangeList := TMethodList.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TSynEditPointBase.Create(Lines : TSynEditStrings);
|
||||||
|
begin
|
||||||
|
Create;
|
||||||
|
FLines := Lines;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TSynEditPointBase.Destroy;
|
||||||
|
begin
|
||||||
|
FreeAndNil(FOnChangeList);
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditPointBase.AddChangeHandler(AHandler : TNotifyEvent);
|
||||||
|
begin
|
||||||
|
FOnChangeList.Add(TMethod(AHandler));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditPointBase.RemoveChangeHandler(AHandler : TNotifyEvent);
|
||||||
|
begin
|
||||||
|
FOnChangeList.Remove(TMethod(AHandler));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSynEditCaret }
|
||||||
|
|
||||||
|
function TSynEditCaret.GetLineCharPos : TPoint;
|
||||||
|
begin
|
||||||
|
Result := Point(fCharPos, fLinePos);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditCaret.SetLineCharPos(const AValue : TPoint);
|
||||||
|
begin
|
||||||
|
if (fCharPos = AValue.X) and (fLinePos = AValue.Y) then exit;
|
||||||
|
fCharPos:= AValue.X;
|
||||||
|
fLinePos:= AValue.Y;
|
||||||
|
fOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditCaret.setCharPos(const AValue : Integer);
|
||||||
|
begin
|
||||||
|
if fCharPos = AValue then exit;
|
||||||
|
fCharPos:= AValue;
|
||||||
|
fOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditCaret.setLinePos(const AValue : Integer);
|
||||||
|
begin
|
||||||
|
if fLinePos = AValue then exit;
|
||||||
|
fLinePos:= AValue;
|
||||||
|
fOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditCaret.GetLineText : string;
|
||||||
|
begin
|
||||||
|
if (LinePos >= 1) and (LinePos <= FLines.Count) then
|
||||||
|
Result := FLines[LinePos - 1]
|
||||||
|
else
|
||||||
|
Result := '';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditCaret.SetLineText(const AValue : string);
|
||||||
|
begin
|
||||||
|
if (LinePos >= 1) and (LinePos <= Max(1, FLines.Count)) then
|
||||||
|
FLines[LinePos - 1] := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TSynEditCaret.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
fLinePos:= 1;
|
||||||
|
fCharPos:= 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TSynEditSelection }
|
||||||
|
|
||||||
|
constructor TSynEditSelection.Create(ALines : TSynEditStrings);
|
||||||
|
begin
|
||||||
|
Inherited Create(ALines);
|
||||||
|
fMaxLeftChar := 1024;
|
||||||
|
FSelectionMode := smNormal;
|
||||||
|
FStartLinePos := 1;
|
||||||
|
FStartBytePos := 1;
|
||||||
|
FEndLinePos := 1;
|
||||||
|
FEndBytePos := 1;
|
||||||
|
FEnabled := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.GetSelText : string;
|
||||||
|
|
||||||
|
function CopyPadded(const S: string; Index, Count: integer): string;
|
||||||
|
var
|
||||||
|
SrcLen: Integer;
|
||||||
|
DstLen: integer;
|
||||||
|
P: PChar;
|
||||||
|
begin
|
||||||
|
SrcLen := Length(S);
|
||||||
|
DstLen := Index + Count;
|
||||||
|
if SrcLen >= DstLen then
|
||||||
|
Result := Copy(S, Index, Count)
|
||||||
|
else begin
|
||||||
|
SetLength(Result, DstLen);
|
||||||
|
P := PChar(Pointer(Result));
|
||||||
|
StrPCopy(P, Copy(S, Index, Count));
|
||||||
|
Inc(P, SrcLen);
|
||||||
|
FillChar(P^, DstLen - Srclen, $20);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure CopyAndForward(const S: string; Index, Count: Integer; var P:
|
||||||
|
PChar);
|
||||||
|
var
|
||||||
|
pSrc: PChar;
|
||||||
|
SrcLen: Integer;
|
||||||
|
DstLen: Integer;
|
||||||
|
begin
|
||||||
|
SrcLen := Length(S);
|
||||||
|
if (Index <= SrcLen) and (Count > 0) then begin
|
||||||
|
Dec(Index);
|
||||||
|
pSrc := PChar(Pointer(S)) + Index;
|
||||||
|
DstLen := Min(SrcLen - Index, Count);
|
||||||
|
Move(pSrc^, P^, DstLen);
|
||||||
|
Inc(P, DstLen);
|
||||||
|
P^ := #0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure CopyPaddedAndForward(const S: string; Index, Count: Integer;
|
||||||
|
var P: PChar);
|
||||||
|
var
|
||||||
|
OldP: PChar;
|
||||||
|
Len: Integer;
|
||||||
|
begin
|
||||||
|
OldP := P;
|
||||||
|
CopyAndForward(S, Index, Count, P);
|
||||||
|
Len := Count - (P - OldP);
|
||||||
|
FillChar(P^, Len, #$20);
|
||||||
|
Inc(P, Len);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
sLineBreak = {$IFDEF SYN_LAZARUS}LineEnding{$ELSE}#$0D#$0A{$ENDIF};
|
||||||
|
var
|
||||||
|
First, Last, TotalLen: Integer;
|
||||||
|
ColFrom, ColTo: Integer;
|
||||||
|
I: Integer;
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
l, r: Integer;
|
||||||
|
s: string;
|
||||||
|
{$ELSE}
|
||||||
|
ColLen: integer;
|
||||||
|
{$ENDIF}
|
||||||
|
P: PChar;
|
||||||
|
begin
|
||||||
|
if not SelAvail then
|
||||||
|
Result := ''
|
||||||
|
else begin
|
||||||
|
if IsBackwardSel then begin
|
||||||
|
ColFrom := FEndBytePos;
|
||||||
|
First := FEndLinePos - 1;
|
||||||
|
ColTo := FStartBytePos;
|
||||||
|
Last := FStartLinePos - 1;
|
||||||
|
end else begin
|
||||||
|
ColFrom := FStartBytePos;
|
||||||
|
First := FStartLinePos - 1;
|
||||||
|
ColTo := FEndBytePos;
|
||||||
|
Last := FEndLinePos - 1;
|
||||||
|
end;
|
||||||
|
TotalLen := 0;
|
||||||
|
case SelectionMode of
|
||||||
|
smNormal:
|
||||||
|
if (First = Last) then
|
||||||
|
Result := Copy(FLines[First], ColFrom, ColTo - ColFrom)
|
||||||
|
else begin
|
||||||
|
// step1: calculate total length of result string
|
||||||
|
TotalLen := Max(0, Length(FLines[First]) - ColFrom + 1);
|
||||||
|
for i := First + 1 to Last - 1 do
|
||||||
|
Inc(TotalLen, Length(FLines[i]));
|
||||||
|
Inc(TotalLen, ColTo - 1);
|
||||||
|
Inc(TotalLen, Length(sLineBreak) * (Last - First));
|
||||||
|
// step2: build up result string
|
||||||
|
SetLength(Result, TotalLen);
|
||||||
|
P := PChar(Pointer(Result));
|
||||||
|
CopyAndForward(FLines[First], ColFrom, MaxInt, P);
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
for i := First + 1 to Last - 1 do begin
|
||||||
|
CopyAndForward(FLines[i], 1, MaxInt, P);
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
end;
|
||||||
|
{$IFDEF SYN_LAZARUS}
|
||||||
|
CopyPaddedAndForward(FLines[Last], 1, ColTo - 1, P);
|
||||||
|
{$ELSE}
|
||||||
|
CopyAndForward(FLines[Last], 1, ColTo - 1, P);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
smColumn:
|
||||||
|
begin
|
||||||
|
if ColFrom > ColTo then
|
||||||
|
SwapInt(ColFrom, ColTo);
|
||||||
|
// step1: calclate total length of result string
|
||||||
|
{$IFNDEF SYN_MBCSSUPPORT}
|
||||||
|
ColLen := ColTo - ColFrom;
|
||||||
|
TotalLen := ColLen + (ColLen + Length(sLineBreak)) * (Last - First);
|
||||||
|
// step2: build up result string
|
||||||
|
SetLength(Result, TotalLen);
|
||||||
|
P := PChar(Pointer(Result));
|
||||||
|
for i := First to Last - 1 do begin
|
||||||
|
CopyPaddedAndForward(FLines[i], ColFrom, ColLen, P);
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
end;
|
||||||
|
CopyPaddedAndForward(FLines[Last], ColFrom, ColLen, P);
|
||||||
|
{$ELSE} //SYN_MBCSSUPPORT
|
||||||
|
for i := First to Last do begin
|
||||||
|
s := FLines[i];
|
||||||
|
l := ColFrom;
|
||||||
|
r := ColTo;
|
||||||
|
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
|
||||||
|
Inc(TotalLen, r - l);
|
||||||
|
end;
|
||||||
|
Inc(TotalLen, Length(sLineBreak) * (Last - First));
|
||||||
|
// step2: build up result string
|
||||||
|
SetLength(Result, TotalLen);
|
||||||
|
P := PChar(Result);
|
||||||
|
for i := First to Last - 1 do begin
|
||||||
|
s := FLines[i];
|
||||||
|
l := ColFrom;
|
||||||
|
r := ColTo;
|
||||||
|
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
|
||||||
|
CopyPaddedAndForward(s, l, r - l, P);
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
end;
|
||||||
|
s := FLines[Last];
|
||||||
|
l := ColFrom;
|
||||||
|
r := ColTo;
|
||||||
|
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
|
||||||
|
CopyPaddedAndForward(FLines[Last], l, r - l, P);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
smLine:
|
||||||
|
begin
|
||||||
|
// If block selection includes LastLine,
|
||||||
|
// line break code(s) of the last line will not be added.
|
||||||
|
// step1: calclate total length of result string
|
||||||
|
for i := First to Last do
|
||||||
|
Inc(TotalLen, Length(FLines[i]) + Length(sLineBreak));
|
||||||
|
if Last = FLines.Count then
|
||||||
|
Dec(TotalLen, Length(sLineBreak));
|
||||||
|
// step2: build up result string
|
||||||
|
SetLength(Result, TotalLen);
|
||||||
|
P := PChar(Pointer(Result));
|
||||||
|
for i := First to Last - 1 do begin
|
||||||
|
CopyAndForward(FLines[i], 1, MaxInt, P);
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
end;
|
||||||
|
CopyAndForward(FLines[Last], 1, MaxInt, P);
|
||||||
|
if (Last + 1) < FLines.Count then
|
||||||
|
CopyAndForward(sLineBreak, 1, MaxInt, P);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetSelText(const Value : string);
|
||||||
|
var
|
||||||
|
StartOfBlock, EndOfBlock: TPoint;
|
||||||
|
begin
|
||||||
|
if SelAvail then begin
|
||||||
|
if IsBackwardSel then
|
||||||
|
fUndoList.AddChange(crDelete, StartLineBytePos, EndLineBytePos,
|
||||||
|
GetSelText, SelectionMode)
|
||||||
|
else
|
||||||
|
fUndoList.AddChange(crDeleteAfterCursor, EndLineBytePos, StartLineBytePos,
|
||||||
|
GetSelText, SelectionMode);
|
||||||
|
StartOfBlock := FirstLineBytePos;
|
||||||
|
EndOfBlock := LastLineBytePos;
|
||||||
|
end else begin
|
||||||
|
StartOfBlock := FCaret.LineCharPos;
|
||||||
|
EndOfBlock := FCaret.LineCharPos;
|
||||||
|
end;
|
||||||
|
StartLineBytePos := StartOfBlock;
|
||||||
|
EndLineBytePos := EndOfBlock;
|
||||||
|
SetSelTextPrimitive(smNormal, PChar(Value), nil);
|
||||||
|
if SelectionMode = smLine then
|
||||||
|
StartOfBlock.X := 1;
|
||||||
|
if length(Value) > 0 then
|
||||||
|
fUndoList.AddChange(crInsert, StartOfBlock, EndLineBytePos, '', smNormal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetSelTextPrimitive(PasteMode : TSynSelectionMode; Value : PChar; ATag : PInteger);
|
||||||
|
var
|
||||||
|
BB, BE: TPoint;
|
||||||
|
TempString: string;
|
||||||
|
|
||||||
|
procedure DeleteSelection;
|
||||||
|
var
|
||||||
|
x, MarkOffset: Integer;
|
||||||
|
UpdateMarks: boolean;
|
||||||
|
NewCaretXY: TPoint;
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
l, r: Integer;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
UpdateMarks := FALSE;
|
||||||
|
MarkOffset := 0;
|
||||||
|
case SelectionMode of
|
||||||
|
smNormal:
|
||||||
|
begin
|
||||||
|
NewCaretXY := FLines.LogicalToPhysicalPos(BB);
|
||||||
|
if FLines.Count > 0 then begin
|
||||||
|
// Create a string that contains everything on the first line up
|
||||||
|
// to the selection mark, and everything on the last line after
|
||||||
|
// the selection mark.
|
||||||
|
TempString := Copy(FLines[BB.Y - 1], 1, BB.X - 1) +
|
||||||
|
Copy(FLines[BE.Y - 1], BE.X, MaxInt);
|
||||||
|
// Delete all FLines in the selection range.
|
||||||
|
TSynEditStrings(FLines).DeleteLines(BB.Y-1, BE.Y - BB.Y);
|
||||||
|
FLines[BB.Y - 1] := TempString;
|
||||||
|
end;
|
||||||
|
UpdateMarks := TRUE;
|
||||||
|
FCaret.LineCharPos := NewCaretXY;
|
||||||
|
end;
|
||||||
|
smColumn:
|
||||||
|
begin
|
||||||
|
// swap X if needed
|
||||||
|
if BB.X > BE.X then
|
||||||
|
{$IFDEF SYN_COMPILER_3_UP}
|
||||||
|
SwapInt(BB.X, BE.X);
|
||||||
|
{$ELSE}
|
||||||
|
begin
|
||||||
|
x := BB.X;
|
||||||
|
BB.X := BE.X;
|
||||||
|
BE.X := x;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
NewCaretXY := FLines.LogicalToPhysicalPos(Point(BB.X, FEndLinePos));
|
||||||
|
for x := BB.Y - 1 to BE.Y - 1 do begin
|
||||||
|
TempString := FLines[x];
|
||||||
|
{$IFNDEF SYN_MBCSSUPPORT}
|
||||||
|
Delete(TempString, BB.X, BE.X - BB.X);
|
||||||
|
{$ELSE}
|
||||||
|
l := BB.X;
|
||||||
|
r := BE.X;
|
||||||
|
MBCSGetSelRangeInLineWhenColumnSelectionMode(TempString, l, r);
|
||||||
|
{$IFDEF USE_UTF8BIDI_LCL}
|
||||||
|
VDelete(TempString, l, r - 1);
|
||||||
|
{$ELSE USE_UTF8BIDI_LCL}
|
||||||
|
Delete(TempString, l, r - l);
|
||||||
|
{$ENDIF USE_UTF8BIDI_LCL}
|
||||||
|
{$ENDIF}
|
||||||
|
FLines[x] := TempString;
|
||||||
|
end;
|
||||||
|
// FLines never get deleted completely, so keep caret at end.
|
||||||
|
FCaret.LineCharPos := NewCaretXY;
|
||||||
|
// Column deletion never removes a line entirely, so no mark
|
||||||
|
// updating is needed here.
|
||||||
|
end;
|
||||||
|
smLine:
|
||||||
|
begin
|
||||||
|
if BE.Y = FLines.Count then begin
|
||||||
|
FLines[BE.Y - 1] := '';
|
||||||
|
for x := BE.Y - 2 downto BB.Y - 1 do
|
||||||
|
FLines.Delete(x);
|
||||||
|
end else
|
||||||
|
for x := BE.Y - 1 downto BB.Y - 1 do
|
||||||
|
FLines.Delete(x);
|
||||||
|
// smLine deletion always resets to first column.
|
||||||
|
FCaret.LineCharPos := Point(1, BB.Y);
|
||||||
|
UpdateMarks := TRUE;
|
||||||
|
MarkOffset := 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
// Update marks
|
||||||
|
if UpdateMarks then
|
||||||
|
FLinesDeletedMethod(BB.Y, BE.Y - BB.Y + MarkOffset);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InsertText;
|
||||||
|
|
||||||
|
function CountLines(p: PChar): integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
while p^ <> #0 do begin
|
||||||
|
if p^ = #13 then
|
||||||
|
Inc(p);
|
||||||
|
if p^ = #10 then
|
||||||
|
Inc(p);
|
||||||
|
Inc(Result);
|
||||||
|
p := GetEOL(p);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InsertNormal: Integer;
|
||||||
|
var
|
||||||
|
sLeftSide: string;
|
||||||
|
sRightSide: string;
|
||||||
|
Str: string;
|
||||||
|
Start: PChar;
|
||||||
|
P: PChar;
|
||||||
|
LogCaretXY: TPoint;
|
||||||
|
PhysicalLineEndPos: LongInt;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
LogCaretXY := FLines.PhysicalToLogicalPos(FCaret.LineCharPos);
|
||||||
|
sLeftSide := Copy(FCaret.LineText, 1, LogCaretXY.X - 1);
|
||||||
|
if LogCaretXY.X - 1 > Length(sLeftSide) then begin
|
||||||
|
PhysicalLineEndPos:= FLines.LogicalToPhysicalPos
|
||||||
|
(Point(Length(sLeftSide)+1, FCaret.LinePos)).X-1;
|
||||||
|
sLeftSide := sLeftSide
|
||||||
|
+ CreateTabsAndSpaces(FCaret.CharPos,
|
||||||
|
FCaret.CharPos-1-PhysicalLineEndPos,
|
||||||
|
FLines.TabWidth,
|
||||||
|
FSpacesToTabs);
|
||||||
|
end;
|
||||||
|
sRightSide := Copy(FCaret.LineText, LogCaretXY.X,
|
||||||
|
Length(FCaret.LineText) - (LogCaretXY.X - 1));
|
||||||
|
// step1: insert the first line of Value into current line
|
||||||
|
Start := PChar(Value);
|
||||||
|
P := GetEOL(Start);
|
||||||
|
if P^ <> #0 then begin
|
||||||
|
SetString(Str, Value, P - Start);
|
||||||
|
TSynEditStrings(FLines).InsertLines(FCaret.LinePos - 1, CountLines(P));
|
||||||
|
FLines[FCaret.LinePos - 1] := sLeftSide + Str;
|
||||||
|
end else begin
|
||||||
|
FLines[FCaret.LinePos - 1] := sLeftSide + Value + sRightSide;
|
||||||
|
FCaret.CharPos := FLines.LogicalToPhysicalPos(
|
||||||
|
Point(1 + Length(sLeftSide + Value),
|
||||||
|
FCaret.LinePos)).X;
|
||||||
|
end;
|
||||||
|
// step2: insert left lines of Value
|
||||||
|
while P^ <> #0 do begin
|
||||||
|
if P^ = #13 then
|
||||||
|
Inc(P);
|
||||||
|
if P^ = #10 then
|
||||||
|
Inc(P);
|
||||||
|
FCaret.LinePos := FCaret.LinePos + 1;
|
||||||
|
Start := P;
|
||||||
|
P := GetEOL(Start);
|
||||||
|
if P = Start then begin
|
||||||
|
if p^ <> #0 then
|
||||||
|
FLines[FCaret.LinePos - 1] := ''
|
||||||
|
else
|
||||||
|
FLines[FCaret.LinePos - 1] := sRightSide;
|
||||||
|
end else begin
|
||||||
|
SetString(Str, Start, P - Start);
|
||||||
|
if p^ <> #0 then
|
||||||
|
FLines[FCaret.LinePos - 1] := Str
|
||||||
|
else
|
||||||
|
FLines[FCaret.LinePos - 1] := Str + sRightSide
|
||||||
|
end;
|
||||||
|
if p^=#0 then
|
||||||
|
FCaret.CharPos := FLines.LogicalToPhysicalPos(
|
||||||
|
Point(1 + Length(FLines[FCaret.LinePos - 1]) - Length(sRightSide),
|
||||||
|
FCaret.LinePos)).X;
|
||||||
|
Inc(Result);
|
||||||
|
end;
|
||||||
|
// StatusChanged([scCaretX]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InsertColumn: Integer;
|
||||||
|
var
|
||||||
|
Str: string;
|
||||||
|
Start: PChar;
|
||||||
|
P: PChar;
|
||||||
|
Len: Integer;
|
||||||
|
InsertPos: Integer;
|
||||||
|
LogicalInsertPos: Integer;
|
||||||
|
begin
|
||||||
|
// Insert string at current position
|
||||||
|
InsertPos := FCaret.CharPos;
|
||||||
|
Start := PChar(Value);
|
||||||
|
repeat
|
||||||
|
P := GetEOL(Start);
|
||||||
|
if P <> Start then begin
|
||||||
|
SetLength(Str, P - Start);
|
||||||
|
Move(Start^, Str[1], P - Start);
|
||||||
|
if FCaret.LinePos > FLines.Count then
|
||||||
|
FLines.Add(StringOfChar(' ', InsertPos - 1) + Str)
|
||||||
|
else begin
|
||||||
|
TempString := FLines[FCaret.LinePos - 1];
|
||||||
|
Len := Length(TempString);
|
||||||
|
LogicalInsertPos := FLines.PhysicalToLogicalCol(TempString,InsertPos);
|
||||||
|
if Len < LogicalInsertPos
|
||||||
|
then begin
|
||||||
|
TempString :=
|
||||||
|
TempString + StringOfChar(' ', LogicalInsertPos - Len - 1)
|
||||||
|
+ Str
|
||||||
|
end else begin
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
if mbTrailByte = ByteType(TempString, InsertPos) then
|
||||||
|
Insert(Str, TempString, InsertPos + 1)
|
||||||
|
else
|
||||||
|
{$ENDIF}
|
||||||
|
System.Insert(Str, TempString, LogicalInsertPos);
|
||||||
|
end;
|
||||||
|
FLines[FCaret.LinePos - 1] := TempString;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if ATag <> nil then
|
||||||
|
ATag^ := P - Start;
|
||||||
|
if p^ in [#10,#13] then begin
|
||||||
|
if (p[1] in [#10,#13]) and (p[1]<>p^) then
|
||||||
|
inc(p,2)
|
||||||
|
else
|
||||||
|
Inc(P);
|
||||||
|
FCaret.LinePos := FCaret.LinePos + 1;
|
||||||
|
end;
|
||||||
|
Start := P;
|
||||||
|
until P^ = #0;
|
||||||
|
FCaret.CharPos:= FCaret.CharPos + Length(Str);
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InsertLine: Integer;
|
||||||
|
var
|
||||||
|
Start: PChar;
|
||||||
|
P: PChar;
|
||||||
|
Str: string;
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
FCaret.CharPos := 1;
|
||||||
|
// Insert string before current line
|
||||||
|
Start := PChar(Value);
|
||||||
|
repeat
|
||||||
|
P := GetEOL(Start);
|
||||||
|
if P <> Start then begin
|
||||||
|
SetLength(Str, P - Start);
|
||||||
|
Move(Start^, Str[1], P - Start);
|
||||||
|
end else
|
||||||
|
Str := '';
|
||||||
|
if (P^ = #0) then begin // Not a full line?
|
||||||
|
n := FLines.Count;
|
||||||
|
if (n >= FCaret.LinePos) then
|
||||||
|
FLines[FCaret.LinePos - 1] := Str + FLines[FCaret.LinePos - 1]
|
||||||
|
else
|
||||||
|
FLines.Add(Str);
|
||||||
|
FCaret.CharPos := 1 + Length(Str);
|
||||||
|
end else begin
|
||||||
|
FLines.Insert(FCaret.LinePos - 1, Str);
|
||||||
|
FCaret.LinePos := FCaret.LinePos + 1;
|
||||||
|
Inc(Result);
|
||||||
|
if P^ = #13 then
|
||||||
|
Inc(P);
|
||||||
|
if P^ = #10 then
|
||||||
|
Inc(P);
|
||||||
|
Start := P;
|
||||||
|
end;
|
||||||
|
until P^ = #0;
|
||||||
|
// StatusChanged([scCaretX]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
StartLine: Integer;
|
||||||
|
InsertedLines: Integer;
|
||||||
|
begin
|
||||||
|
if Value = '' then
|
||||||
|
Exit;
|
||||||
|
if FLines.Count = 0 then
|
||||||
|
FLines.Add('');
|
||||||
|
|
||||||
|
// Using a TStringList to do this would be easier, but if we're dealing
|
||||||
|
// with a large block of text, it would be very inefficient. Consider:
|
||||||
|
// Assign Value parameter to TStringList.Text: that parses through it and
|
||||||
|
// creates a copy of the string for each line it finds. That copy is passed
|
||||||
|
// to the Add method, which in turn creates a copy. Then, when you actually
|
||||||
|
// use an item in the list, that creates a copy to return to you. That's
|
||||||
|
// 3 copies of every string vs. our one copy below. I'd prefer no copies,
|
||||||
|
// but we aren't set up to work with PChars that well.
|
||||||
|
|
||||||
|
StartLine := FCaret.LinePos;
|
||||||
|
case PasteMode of
|
||||||
|
smNormal:
|
||||||
|
InsertedLines := InsertNormal;
|
||||||
|
smColumn:
|
||||||
|
InsertedLines := InsertColumn;
|
||||||
|
smLine:
|
||||||
|
InsertedLines := InsertLine;
|
||||||
|
else
|
||||||
|
InsertedLines := 0;
|
||||||
|
end;
|
||||||
|
// We delete selected based on the current selection mode, but paste
|
||||||
|
// what's on the clipboard according to what it was when copied.
|
||||||
|
// Update marks
|
||||||
|
if InsertedLines > 0 then
|
||||||
|
FLinesInsertedMethod(StartLine, InsertedLines);
|
||||||
|
// Force caret reset
|
||||||
|
// CaretXY := CaretXY;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FLines.BeginUpdate;
|
||||||
|
try
|
||||||
|
// BB is lower than BE
|
||||||
|
BB := FirstLineBytePos;
|
||||||
|
BE := LastLineBytePos;
|
||||||
|
if SelAvail then
|
||||||
|
DeleteSelection;
|
||||||
|
if (Value <> nil) and (Value[0] <> #0) then
|
||||||
|
InsertText;
|
||||||
|
finally
|
||||||
|
FLines.EndUpdate; // May reset Block Begin
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.GetStartLineBytePos : TPoint;
|
||||||
|
begin
|
||||||
|
Result.y := FStartLinePos;
|
||||||
|
Result.x := FStartBytePos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetEnabled(const Value : Boolean);
|
||||||
|
begin
|
||||||
|
if FEnabled = Value then exit;
|
||||||
|
FEnabled := Value;
|
||||||
|
if not Enabled then SetStartLineBytePos(EndLineBytePos);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetStartLineBytePos(Value : TPoint);
|
||||||
|
// logical position (byte)
|
||||||
|
var
|
||||||
|
nInval1, nInval2: integer;
|
||||||
|
SelChanged: boolean;
|
||||||
|
begin
|
||||||
|
Value.x := MinMax(Value.x, 1, fMaxLeftChar);
|
||||||
|
Value.y := MinMax(Value.y, 1, fLines.Count);
|
||||||
|
if (SelectionMode = smNormal) then
|
||||||
|
if (Value.y >= 1) and (Value.y <= FLines.Count) then
|
||||||
|
Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x)
|
||||||
|
else
|
||||||
|
Value.x := 1;
|
||||||
|
if SelAvail then begin
|
||||||
|
if FStartLinePos < FEndLinePos then begin
|
||||||
|
nInval1 := Min(Value.Y, FStartLinePos);
|
||||||
|
nInval2 := Max(Value.Y, FEndLinePos);
|
||||||
|
end else begin
|
||||||
|
nInval1 := Min(Value.Y, FEndLinePos);
|
||||||
|
nInval2 := Max(Value.Y, FStartLinePos);
|
||||||
|
end;
|
||||||
|
FInvalidateLinesMethod(nInval1, nInval2);
|
||||||
|
SelChanged := TRUE;
|
||||||
|
end else begin
|
||||||
|
SelChanged := (FStartBytePos <> Value.X) or (FStartLinePos <> Value.Y) or
|
||||||
|
(FEndBytePos <> Value.X) or (FEndLinePos <> Value.Y);
|
||||||
|
end;
|
||||||
|
FStartLinePos := Value.Y;
|
||||||
|
FStartBytePos := Value.X;
|
||||||
|
FEndLinePos := Value.Y;
|
||||||
|
FEndBytePos := Value.X;
|
||||||
|
if SelChanged then
|
||||||
|
fOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.GetEndLineBytePos : TPoint;
|
||||||
|
begin
|
||||||
|
Result.y := FEndLinePos;
|
||||||
|
Result.x := FEndBytePos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetEndLineBytePos(Value : TPoint);
|
||||||
|
var
|
||||||
|
nLine: integer;
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
s: string;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
if FEnabled then begin
|
||||||
|
Value.x := MinMax(Value.x, 1, fMaxLeftChar);
|
||||||
|
Value.y := MinMax(Value.y, 1, fLines.Count);
|
||||||
|
if (SelectionMode = smNormal) then
|
||||||
|
if (Value.y >= 1) and (Value.y <= fLines.Count) then
|
||||||
|
Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x)
|
||||||
|
else
|
||||||
|
Value.x := 1;
|
||||||
|
if (Value.X <> FEndBytePos) or (Value.Y <> FEndLinePos) then begin
|
||||||
|
{$IFDEF SYN_MBCSSUPPORT}
|
||||||
|
if Value.Y <= fLines.Count then begin
|
||||||
|
s := fLines[Value.Y - 1];
|
||||||
|
if (Length(s) >= Value.X) and (mbTrailByte = ByteType(s, Value.X)) then
|
||||||
|
Dec(Value.X);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
if (Value.X <> FEndBytePos) or (Value.Y <> FEndLinePos) then begin
|
||||||
|
if (SelectionMode = smColumn) and (Value.X <> FEndBytePos) then begin
|
||||||
|
FInvalidateLinesMethod(
|
||||||
|
Min(FStartLinePos, Min(FEndLinePos, Value.Y)),
|
||||||
|
Max(FStartLinePos, Max(FEndLinePos, Value.Y)));
|
||||||
|
FEndLinePos := Value.Y;
|
||||||
|
FEndBytePos := Value.X;
|
||||||
|
end else begin
|
||||||
|
nLine := FEndLinePos;
|
||||||
|
FEndLinePos := Value.Y;
|
||||||
|
FEndBytePos := Value.X;
|
||||||
|
if (SelectionMode <> smColumn) or (FStartBytePos <> FEndBytePos) then
|
||||||
|
FInvalidateLinesMethod(nLine, FEndLinePos);
|
||||||
|
end;
|
||||||
|
FOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditSelection.SetSelectionMode(const Value: TSynSelectionMode);
|
||||||
|
begin
|
||||||
|
if FSelectionMode <> Value then begin
|
||||||
|
FSelectionMode := Value;
|
||||||
|
if SelAvail then
|
||||||
|
FInvalidateLinesMethod(-1, -1);
|
||||||
|
FOnChangeList.CallNotifyEvents(self);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.AdjustBytePosToCharacterStart(Line : integer; BytePos : integer) : integer;
|
||||||
|
var
|
||||||
|
s: string;
|
||||||
|
begin
|
||||||
|
Result := BytePos;
|
||||||
|
if Result < 1 then
|
||||||
|
Result := 1
|
||||||
|
else if (Line >= 1) and (Line <= FLines.Count) then begin
|
||||||
|
s := FLines[Line-1];
|
||||||
|
if (Result <= length(s)) and FLines.IsUtf8 then
|
||||||
|
Result:=UTF8FindNearestCharStart(PChar(Pointer(s)),length(s),Result);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.GetFirstLineBytePos: TPoint;
|
||||||
|
begin
|
||||||
|
if IsBackwardSel then
|
||||||
|
Result := EndLineBytePos
|
||||||
|
else
|
||||||
|
Result := StartLineBytePos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.GetLastLineBytePos: TPoint;
|
||||||
|
begin
|
||||||
|
if IsBackwardSel then
|
||||||
|
Result := StartLineBytePos
|
||||||
|
else
|
||||||
|
Result := EndLineBytePos;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.SelAvail : Boolean;
|
||||||
|
begin
|
||||||
|
Result := (FStartBytePos <> FEndBytePos) or
|
||||||
|
((FStartLinePos <> FEndLinePos) and (FSelectionMode <> smColumn));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditSelection.IsBackwardSel: Boolean;
|
||||||
|
begin
|
||||||
|
Result := (FStartLinePos > FEndLinePos)
|
||||||
|
or ((FStartLinePos = FEndLinePos) and (FStartBytePos > FEndBytePos));
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -26,7 +26,7 @@ unit SynEditTextBase;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, SynEditTypes;
|
Classes, SysUtils, LCLProc, SynEditTypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -34,6 +34,12 @@ type
|
|||||||
|
|
||||||
TSynEditStrings = class(TStrings)
|
TSynEditStrings = class(TStrings)
|
||||||
protected
|
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 GetFoldEndLevel(Index: integer): integer; virtual; abstract;
|
||||||
function GetFoldMinLevel(Index: integer): integer; virtual; abstract;
|
function GetFoldMinLevel(Index: integer): integer; virtual; abstract;
|
||||||
procedure SetFoldEndLevel(Index: integer; const AValue: integer); virtual; abstract;
|
procedure SetFoldEndLevel(Index: integer; const AValue: integer); virtual; abstract;
|
||||||
@ -44,13 +50,29 @@ type
|
|||||||
function GetLengthOfLongestLine: integer; virtual; abstract;
|
function GetLengthOfLongestLine: integer; virtual; abstract;
|
||||||
procedure SetTextStr(const Value: string); override;
|
procedure SetTextStr(const Value: string); override;
|
||||||
public
|
public
|
||||||
|
constructor Create;
|
||||||
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
|
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
|
||||||
procedure InsertLines(Index, NumLines: integer); virtual; abstract;
|
procedure InsertLines(Index, NumLines: integer); virtual; abstract;
|
||||||
procedure InsertStrings(Index: integer; NewStrings: TStrings); virtual; abstract;
|
procedure InsertStrings(Index: integer; NewStrings: TStrings); virtual; abstract;
|
||||||
procedure ClearRanges(ARange: TSynEditRange); 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
|
public
|
||||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
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 Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
||||||
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel
|
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel
|
||||||
write SetFoldMinLevel;
|
write SetFoldMinLevel;
|
||||||
@ -64,6 +86,33 @@ implementation
|
|||||||
|
|
||||||
{ TSynEditStrings }
|
{ 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);
|
procedure TSynEditStrings.SetTextStr(const Value : string);
|
||||||
var
|
var
|
||||||
StartPos: Integer;
|
StartPos: Integer;
|
||||||
@ -98,5 +147,96 @@ begin
|
|||||||
end;
|
end;
|
||||||
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.
|
end.
|
||||||
|
|
||||||
|
@ -109,7 +109,6 @@ type
|
|||||||
fSimulateConvertTabsProc: TSimulateConvertTabsProcEx;
|
fSimulateConvertTabsProc: TSimulateConvertTabsProcEx;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
fIndexOfLongestLine: integer;
|
fIndexOfLongestLine: integer;
|
||||||
fTabWidth: integer;
|
|
||||||
{end} //mh 2000-10-19
|
{end} //mh 2000-10-19
|
||||||
fOnChange: TNotifyEvent;
|
fOnChange: TNotifyEvent;
|
||||||
fOnChanging: TNotifyEvent;
|
fOnChanging: TNotifyEvent;
|
||||||
@ -151,7 +150,7 @@ type
|
|||||||
procedure PutObject(Index: integer; AObject: TObject); override;
|
procedure PutObject(Index: integer; AObject: TObject); override;
|
||||||
procedure SetCapacity(NewCapacity: integer);
|
procedure SetCapacity(NewCapacity: integer);
|
||||||
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF} //mh 2000-10-18
|
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF} //mh 2000-10-18
|
||||||
procedure SetTabWidth(Value: integer); //mh 2000-10-19
|
procedure SetTabWidth(const Value: integer); override;
|
||||||
procedure SetUpdateState(Updating: Boolean); override;
|
procedure SetUpdateState(Updating: Boolean); override;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
@ -180,7 +179,6 @@ type
|
|||||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||||
{end} //mh 2000-10-19
|
{end} //mh 2000-10-19
|
||||||
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
||||||
property TabWidth: integer read fTabWidth write SetTabWidth; //mh 2000-10-19
|
|
||||||
property OnAdded: TStringListIndexEvent read fOnAdded write fOnAdded;
|
property OnAdded: TStringListIndexEvent read fOnAdded write fOnAdded;
|
||||||
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
||||||
property OnChanging: TNotifyEvent read fOnChanging write fOnChanging;
|
property OnChanging: TNotifyEvent read fOnChanging write fOnChanging;
|
||||||
@ -501,7 +499,6 @@ begin
|
|||||||
fDosFileFormat := TRUE;
|
fDosFileFormat := TRUE;
|
||||||
{begin} //mh 2000-10-19
|
{begin} //mh 2000-10-19
|
||||||
fIndexOfLongestLine := -1;
|
fIndexOfLongestLine := -1;
|
||||||
TabWidth := 8;
|
|
||||||
{end} //mh 2000-10-19
|
{end} //mh 2000-10-19
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1052,12 +1049,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{begin} //mh 2000-10-19
|
{begin} //mh 2000-10-19
|
||||||
procedure TSynEditStringList.SetTabWidth(Value: integer);
|
procedure TSynEditStringList.SetTabWidth(const Value: integer);
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
if Value <> fTabWidth then begin
|
if Value <> FTabWidth then begin
|
||||||
fTabWidth := Value;
|
Inherited SetTabWidth(Value);
|
||||||
fConvertTabsProc := GetBestConvertTabsProcEx(fTabWidth);
|
fConvertTabsProc := GetBestConvertTabsProcEx(fTabWidth);
|
||||||
{$IFDEF SYN_LAZARUS}
|
{$IFDEF SYN_LAZARUS}
|
||||||
fSimulateConvertTabsProc := GetBestSimulateConvertTabsProcEx(fTabWidth);
|
fSimulateConvertTabsProc := GetBestSimulateConvertTabsProcEx(fTabWidth);
|
||||||
|
@ -28,7 +28,8 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
LCLProc,
|
LCLProc,
|
||||||
Classes, SysUtils, SynEditTypes, SynEditTextBase, SynEditTextBuffer, SynEditMiscClasses;
|
Classes, SysUtils, SynEditTypes, SynEditTextBase, SynEditTextBuffer,
|
||||||
|
SynEditMiscClasses, SynEditPointClasses;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -52,6 +53,10 @@ type
|
|||||||
procedure DoLinesChanged(Index, N: integer);
|
procedure DoLinesChanged(Index, N: integer);
|
||||||
procedure TrimAfterLock;
|
procedure TrimAfterLock;
|
||||||
protected
|
protected
|
||||||
|
function GetIsUtf8 : Boolean; override;
|
||||||
|
procedure SetIsUtf8(const AValue : Boolean); override;
|
||||||
|
function GetTabWidth : integer; override;
|
||||||
|
procedure SetTabWidth(const AValue : integer); override;
|
||||||
function GetFoldEndLevel(Index: integer): integer; override;
|
function GetFoldEndLevel(Index: integer): integer; override;
|
||||||
function GetFoldMinLevel(Index: integer): integer; override;
|
function GetFoldMinLevel(Index: integer): integer; override;
|
||||||
procedure SetFoldEndLevel(Index: integer; const AValue: integer); override;
|
procedure SetFoldEndLevel(Index: integer; const AValue: integer); override;
|
||||||
@ -104,7 +109,6 @@ implementation
|
|||||||
|
|
||||||
constructor TSynEditStringTrimmingList.Create(ASynStringSource : TSynEditStrings; ACaret: TSynEditCaret);
|
constructor TSynEditStringTrimmingList.Create(ASynStringSource : TSynEditStrings; ACaret: TSynEditCaret);
|
||||||
begin
|
begin
|
||||||
Inherited Create;
|
|
||||||
fSynStrings := ASynStringSource;
|
fSynStrings := ASynStringSource;
|
||||||
fCaret := ACaret;
|
fCaret := ACaret;
|
||||||
fCaret.AddChangeHandler(@DoCaretChanged);
|
fCaret.AddChangeHandler(@DoCaretChanged);
|
||||||
@ -112,6 +116,7 @@ begin
|
|||||||
fLineIndex:= -1;
|
fLineIndex:= -1;
|
||||||
fSpaces := '';
|
fSpaces := '';
|
||||||
fEnabled:=false;
|
fEnabled:=false;
|
||||||
|
Inherited Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSynEditStringTrimmingList.Destroy;
|
destructor TSynEditStringTrimmingList.Destroy;
|
||||||
@ -264,6 +269,26 @@ begin
|
|||||||
fLockList.Clear;
|
fLockList.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynEditStringTrimmingList.GetIsUtf8 : Boolean;
|
||||||
|
begin
|
||||||
|
Result := FSynStrings.IsUtf8;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditStringTrimmingList.SetIsUtf8(const AValue : Boolean);
|
||||||
|
begin
|
||||||
|
FSynStrings.IsUtf8 := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditStringTrimmingList.GetTabWidth : integer;
|
||||||
|
begin
|
||||||
|
Result := FSynStrings.TabWidth;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditStringTrimmingList.SetTabWidth(const AValue : integer);
|
||||||
|
begin
|
||||||
|
FSynStrings.TabWidth := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynEditStringTrimmingList.ForceTrim;
|
procedure TSynEditStringTrimmingList.ForceTrim;
|
||||||
begin
|
begin
|
||||||
TrimAfterLock;
|
TrimAfterLock;
|
||||||
|
Loading…
Reference in New Issue
Block a user