📄 synedittextbuffer.pas
字号:
procedure TSynEditFileWriter.WriteLine(const S: string;
const FileFormat: TSynEditFileFormat);
var
L, NL: Cardinal;
begin
L := Length(S);
NL := 1 + Ord(fFileFormat = sffDos);
repeat
if fBufPtr + L + NL <= fBufSize then begin
if L > 0 then begin
Move(S[1], fBuffer[fBufPtr], L);
fBufPtr := fBufPtr + L;
end;
if (fFileFormat <> sffUnix) then
begin
fBuffer[fBufPtr] := #13; // CR
Inc(fBufPtr);
end;
if (fFileFormat <> sffMac) then
begin
fBuffer[fBufPtr] := #10; // LF
Inc(fBufPtr);
end;
Exit;
end;
Flush;
if L + NL > fBufSize then
SetBufferSize(L + NL);
until False;
end;
{ TSynEditStringList }
procedure ListIndexOutOfBounds(Index: integer);
begin
raise ESynEditStringList.CreateFmt(SListIndexOutOfBounds, [Index]);
end;
constructor TSynEditStringList.Create;
begin
inherited Create;
fFileFormat := sffDos;
fIndexOfLongestLine := -1;
TabWidth := 8;
end;
destructor TSynEditStringList.Destroy;
begin
fOnChange := nil;
fOnChanging := nil;
inherited Destroy;
if fCount <> 0 then
Finalize(fList^[0], fCount);
fCount := 0;
SetCapacity(0);
end;
function TSynEditStringList.Add(const S: string): integer;
begin
BeginUpdate;
Result := fCount;
InsertItem(Result, S);
if Assigned(OnInserted) then
OnInserted( Self, Result, 1 );
EndUpdate;
end;
procedure TSynEditStringList.AddStrings(Strings: TStrings);
var
i, FirstAdded: integer;
begin
if Strings.Count > 0 then begin
fIndexOfLongestLine := -1;
BeginUpdate;
try
i := fCount + Strings.Count;
if i > fCapacity then
SetCapacity((i + 15) and (not 15));
FirstAdded := fCount;
for i := 0 to Strings.Count - 1 do begin
with fList^[fCount] do begin
Pointer(fString) := nil;
fString := Strings[i];
fObject := Strings.Objects[i];
fRange := NullRange;
fExpandedLength := -1;
fFlags := [sfExpandedLengthUnknown];
end;
Inc(fCount);
end;
if Assigned(OnInserted) then
OnInserted( Self, FirstAdded, Strings.Count );
finally
EndUpdate;
end;
end;
end;
procedure TSynEditStringList.Clear;
begin
if fCount <> 0 then begin
BeginUpdate;
Finalize(fList^[0], fCount);
fCount := 0;
SetCapacity(0);
if Assigned(fOnCleared) then
fOnCleared(Self);
EndUpdate;
end;
fIndexOfLongestLine := -1;
end;
procedure TSynEditStringList.Delete(Index: integer);
begin
if (Index < 0) or (Index > fCount) then
ListIndexOutOfBounds(Index);
BeginUpdate;
Finalize(fList^[Index]);
Dec(fCount);
if Index < fCount then begin
System.Move(fList^[Index + 1], fList^[Index],
(fCount - Index) * SynEditStringRecSize);
end;
fIndexOfLongestLine := -1;
if Assigned(fOnDeleted) then
fOnDeleted( Self, Index, 1 );
EndUpdate;
end;
procedure TSynEditStringList.DeleteLines(Index, NumLines: Integer);
var
LinesAfter: integer;
begin
if NumLines > 0 then begin
if (Index < 0) or (Index > fCount) then
ListIndexOutOfBounds(Index);
LinesAfter := fCount - (Index + NumLines - 1);
if LinesAfter < 0 then
NumLines := fCount - Index - 1;
Finalize(fList^[Index], NumLines);
if LinesAfter > 0 then begin
BeginUpdate;
try
System.Move(fList^[Index + NumLines], fList^[Index],
LinesAfter * SynEditStringRecSize);
finally
EndUpdate;
end;
end;
Dec(fCount, NumLines);
if Assigned(fOnDeleted) then
fOnDeleted( Self, Index, NumLines );
end;
end;
procedure TSynEditStringList.Exchange(Index1, Index2: integer);
var
Temp: TSynEditStringRec;
begin
if (Index1 < 0) or (Index1 >= fCount) then
ListIndexOutOfBounds(Index1);
if (Index2 < 0) or (Index2 >= fCount) then
ListIndexOutOfBounds(Index2);
BeginUpdate;
Temp := fList^[Index1];
fList^[Index1] := fList^[Index2];
fList^[Index2] := Temp;
if fIndexOfLongestLine = Index1 then
fIndexOfLongestLine := Index2
else if fIndexOfLongestLine = Index2 then
fIndexOfLongestLine := Index1;
EndUpdate;
end;
function TSynEditStringList.ExpandString(Index: integer): string;
var
HasTabs: boolean;
begin
with fList^[Index] do
if fString = '' then begin
Result := '';
Exclude(fFlags, sfExpandedLengthUnknown);
Exclude(fFlags, sfHasTabs);
Include(fFlags, sfHasNoTabs);
fExpandedLength := 0;
end else begin
Result := fConvertTabsProc(fString, fTabWidth, HasTabs);
fExpandedLength := Length(Result);
Exclude(fFlags, sfExpandedLengthUnknown);
Exclude(fFlags, sfHasTabs);
Exclude(fFlags, sfHasNoTabs);
if HasTabs then
Include(fFlags, sfHasTabs)
else
Include(fFlags, sfHasNoTabs);
end;
end;
function TSynEditStringList.Get(Index: integer): string;
begin
if (Index >= 0) and (Index < fCount) then
Result := fList^[Index].fString
else
Result := '';
end;
function TSynEditStringList.GetCapacity: integer;
begin
Result := fCapacity;
end;
function TSynEditStringList.GetCount: integer;
begin
Result := fCount;
end;
function TSynEditStringList.GetExpandedString(Index: integer): string;
begin
if (Index >= 0) and (Index < fCount) then begin
if sfHasNoTabs in fList^[Index].fFlags then
Result := fList^[Index].fString
else
Result := ExpandString(Index);
end else
Result := '';
end;
function TSynEditStringList.GetExpandedStringLength(Index: integer): integer;
begin
if (Index >= 0) and (Index < fCount) then
begin
if sfExpandedLengthUnknown in fList^[Index].fFlags then
Result := Length( ExpandedStrings[index] )
else
Result := fList^[Index].fExpandedLength;
end
else
Result := 0;
end;
function TSynEditStringList.GetLengthOfLongestLine: integer;
var
i, MaxLen: integer;
PRec: PSynEditStringRec;
begin
if fIndexOfLongestLine < 0 then begin
MaxLen := 0;
if fCount > 0 then begin
PRec := @fList^[0];
for i := 0 to fCount - 1 do begin
if sfExpandedLengthUnknown in PRec^.fFlags then
ExpandString(i);
if PRec^.fExpandedLength > MaxLen then begin
MaxLen := PRec^.fExpandedLength;
fIndexOfLongestLine := i;
end;
Inc(PRec);
end;
end;
end;
if (fIndexOfLongestLine >= 0) and (fIndexOfLongestLine < fCount) then
Result := fList^[fIndexOfLongestLine].fExpandedLength
else
Result := 0;
end;
function TSynEditStringList.GetObject(Index: integer): TObject;
begin
if (Index >= 0) and (Index < fCount) then
Result := fList^[Index].fObject
else
Result := nil;
end;
function TSynEditStringList.GetRange(Index: integer): TSynEditRange;
begin
if (Index >= 0) and (Index < fCount) then
Result := fList^[Index].fRange
else
Result := nil;
end;
function TSynEditStringList.GetTextStr: string;
begin
Result := inherited GetTextStr;
System.Delete(Result, Length(Result) - Length(SLineBreak) + 1, MaxInt);
end;
procedure TSynEditStringList.Grow;
var
Delta: Integer;
begin
if fCapacity > 64 then
Delta := fCapacity div 4
else
Delta := 16;
SetCapacity(fCapacity + Delta);
end;
procedure TSynEditStringList.Insert(Index: integer; const S: string);
begin
if (Index < 0) or (Index > fCount) then
ListIndexOutOfBounds(Index);
BeginUpdate;
InsertItem(Index, S);
if Assigned(fOnInserted) then
fOnInserted( Self, Index, 1 );
EndUpdate;
end;
procedure TSynEditStringList.InsertItem(Index: integer; const S: string);
begin
BeginUpdate;
if fCount = fCapacity then
Grow;
if Index < fCount then begin
System.Move(fList^[Index], fList^[Index + 1],
(fCount - Index) * SynEditStringRecSize);
end;
fIndexOfLongestLine := -1;
with fList^[Index] do begin
Pointer(fString) := nil;
fString := S;
fObject := nil;
fRange := NullRange;
fExpandedLength := -1;
fFlags := [sfExpandedLengthUnknown];
end;
Inc(fCount);
EndUpdate;
end;
procedure TSynEditStringList.InsertLines(Index, NumLines: integer);
begin
if (Index < 0) or (Index > fCount) then
ListIndexOutOfBounds(Index);
if NumLines > 0 then begin
BeginUpdate;
try
SetCapacity(fCount + NumLines);
if Index < fCount then begin
System.Move(fList^[Index], fList^[Index + NumLines],
(fCount - Index) * SynEditStringRecSize);
end;
FillChar(fList^[Index], NumLines * SynEditStringRecSize, 0);
Inc(fCount, NumLines);
if Assigned(OnInserted) then
OnInserted( Self, Index, NumLines );
finally
EndUpdate;
end;
end;
end;
procedure TSynEditStringList.InsertStrings(Index: integer;
NewStrings: TStrings);
var
i, Cnt: integer;
begin
Cnt := NewStrings.Count;
if Cnt = 0 then exit;
BeginUpdate;
try
InsertLines(Index, Cnt);
for i := 0 to Cnt - 1 do
Strings[Index + i] := NewStrings[i];
finally
EndUpdate;
end;
end;
procedure TSynEditStringList.InsertText(Index: integer;
NewText: String);
var
TmpStringList: TStringList;
begin
if NewText = '' then exit;
TmpStringList := TStringList.Create;
try
TmpStringList.Text := NewText;
InsertStrings(Index, TmpStringList);
finally
TmpStringList.Free;
end;
end;
procedure TSynEditStringList.LoadFromFile(const FileName: string);
var
// Reader: TSynEditFileReader;
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
(*//Old Code, for reference
Reader := TSynEditFileReader.Create(FileName);
try
BeginUpdate;
try
Clear;
while not Reader.EOF do
Add(Reader.ReadLine);
fFileFormat := Reader.FileFormat;
finally
EndUpdate;
end;
finally
Reader.Free;
end;
*)
end;
procedure TSynEditStringList.LoadFromStream(Stream: TStream);
var
Size: Integer;
S, S1: string;
P, Start: PChar;
fCR, fLF: Boolean;
iPos: Integer;
begin
fCR := False;
fLF := False;
try
BeginUpdate;
Size := Stream.Size;
Stream.Position := 0;
SetString(S, nil, Size);
Stream.Read(Pointer(S)^, Size);
Clear;
P := Pointer(S);
if P <> nil then
begin
iPos := 0;
while (iPos < Size) do // (P^ <> #0) do
begin
Start := P;
while not (P^ in [#10, #13]) and (iPos < Size) do
begin
Inc(P);
Inc(iPos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -