📄 synedittextbuffer.pas
字号:
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;
fDeleteBlankLineAtEOF := True;
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;
if Assigned(fOnBeforeInserted) then
fOnBeforeInserted( Self, Result, 1 );
InsertItem(Result, S);
if Assigned(fOnInserted) then
fOnInserted( 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];
if Strings is TSynEditStringList then
begin
fAttribute.aMask := TSynEditStringList(Strings).Attributes[i].aMask;
fAttribute.aForeground := TSynEditStringList(Strings).Attributes[i].aForeground;
fAttribute.aBackground := TSynEditStringList(Strings).Attributes[i].aBackground;
fAttribute.aHide := TSynEditStringList(Strings).Attributes[i].aHide;
fAttribute.aLineState := TSynEditStringList(Strings).Attributes[i].aLineState;
end
else
begin
fAttribute.aMask := [];
fAttribute.aForeground := clNone;
fAttribute.aBackground := clNone;
fAttribute.aHide := False;
fAttribute.aLineState := lsModified;
end;
end;
Inc(fCount);
end;
if Assigned(fOnInserted) then
fOnInserted( 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;
if Assigned(fOnBeforeDeleted) then
fOnBeforeDeleted( Self, Index, 1 );
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;
if Assigned(fOnBeforeDeleted) then
fOnBeforeDeleted( Self, Index, NumLines );
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;
if Assigned(fOnBeforeInserted) then
fOnBeforeInserted( Self, Index, 1 );
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];
fAttribute.aHide := false;
fAttribute.aForeground := clNone;
fAttribute.aBackground := clNone;
fAttribute.aMask := [];
fAttribute.aLineState := lsModified;
end;
Inc(fCount);
EndUpdate;
end;
procedure TSynEditStringList.InsertLines(Index, NumLines: integer);
var
rindex : integer;
c_Line: Integer;
begin
if (Index < 0) or (Index > fCount) then
ListIndexOutOfBounds(Index);
if NumLines > 0 then begin
BeginUpdate;
try
//修正 修正在自动换行下粘贴会出错的BUG
rindex := Index;
if Assigned(OnBeforeInserted) then
OnBeforeInserted( Self, rIndex, NumLines );
SetCapacity(fCount + NumLines);
if Index < fCount then begin
System.Move(fList^[Index], fList^[Index + NumLines],
(fCount - Index) * SynEditStringRecSize);
end;
for c_Line := Index to Index + NumLines -1 do
with fList^[c_Line] do
begin
Pointer(fString) := nil;
fObject := nil;
fRange := NullRange;
fExpandedLength := -1;
fFlags := [sfExpandedLengthUnknown];
fAttribute.aMask := [];
fAttribute.aForeground := clnone;
fAttribute.aBackground := clNone;
fAttribute.aHide := False;
fAttribute.aLineState := lsModified;
end;
Inc(fCount, NumLines);
if Assigned(fOnInserted) then
fOnInserted( Self, rIndex, 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);
end;
SetString(S1, Start, P - Start);
Attributes[Add(S1)].aLineState := lsNone;
if (P^ = #13) then
begin
fCR := True;
Inc(P);
Inc(iPos);
end;
if (P^ = #10) then
begin
fLF := True;
Inc(P);
Inc(iPos);
end;
end;
{ keep the old format of the file }
if (not AppendNewLineAtEOF) and (S[Size] in [#10,#13]) then
Add('');
if fDeleteBlankLineAtEOF then
begin
while (Count > 0) and (Length(Trim(Strings[Count - 1])) = 0) do
begin
Delete(Count-1);
end;
end;
end;
finally
EndUpdate;
end;
if fCR and not fLF then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -