📄 syneditwordwrap.pas
字号:
begin
if fMaxRowLength = 0 then
begin
Result := 0;
Exit;
end;
Assert( aIndex >= 0 );
Assert( aCount >= 1 );
Assert( aIndex <= LineCount );
// resize fLineOffsets
GrowLines( LineCount + aCount );
if aIndex < LineCount then // no need for MoveLines if inserting at LineCount (TSynEditStringList.Add)
begin
Inc( fLineCount, aCount ); // fLineCount must be updated before calling MoveLines()
MoveLines( aIndex, aCount );
end
else
Inc( fLineCount, aCount );
// set offset to same as previous line (i.e. the line has 0 rows)
if aIndex = 0 then
vPrevOffset := 0
else
vPrevOffset := fLineOffsets[ aIndex -1 ];
for cLine := aIndex to aIndex + aCount -1 do
fLineOffsets[cLine] := vPrevOffset;
// Rewrap.
Result := 0;
for cLine := aIndex to aIndex + aCount -1 do
Inc( Result, ReWrapLine(cLine) );
end;
function TSynWordWrapPlugin.LinesPutted(aIndex: integer; aCount: integer): integer;
var
cLine: integer;
begin
if fMaxRowLength = 0 then
begin
Result := 0;
Exit;
end;
Assert( aIndex >= 0 );
Assert( aCount >= 1 );
Assert( aIndex + aCount <= LineCount );
// Rewrap.
Result := 0;
for cLine := aIndex to aIndex + aCount -1 do
Inc( Result, ReWrapLine(cLine) );
end;
procedure TSynWordWrapPlugin.MoveLines(aStart: TLineIndex; aMoveBy: integer);
var
vMoveCount: integer;
begin
Assert( aMoveBy <> 0 );
Assert( aStart + aMoveBy >= 0 );
Assert( aStart + aMoveBy < LineCount );
vMoveCount := LineCount - aStart;
if aMoveBy > 0 then
Dec( vMoveCount, aMoveBy );
Move( fLineOffsets[aStart], fLineOffsets[aStart + aMoveBy],
vMoveCount * SizeOf(TRowIndex) );
end;
procedure TSynWordWrapPlugin.MoveRows(aStart: TRowIndex; aMoveBy: integer);
var
vMoveCount: integer;
begin
Assert( aMoveBy <> 0 );
Assert( aStart + aMoveBy >= 0 );
Assert( aStart + aMoveBy < RowCount );
vMoveCount := RowCount - aStart;
if aMoveBy > 0 then
Dec( vMoveCount, aMoveBy );
Move( fRowLengths[aStart], fRowLengths[aStart + aMoveBy],
vMoveCount * SizeOf(TRowLength) );
end;
procedure TSynWordWrapPlugin.Reset;
begin
Assert( Editor.CharsInWindow >= 0 );
fMaxRowLength := Editor.CharsInWindow;
fMinRowLength := Editor.CharsInWindow - (Editor.CharsInWindow div 3);
fBreakChars := [#0..#255] - Editor.IdentChars;
if fMinRowLength <= 0 then
fMinRowLength := 1;
WrapLines;
end;
function TSynWordWrapPlugin.ReWrapLine(aIndex: TLineIndex): integer;
// Returns RowCount delta (how many wrapped lines were added or removed by this change).
var
vMaxNewRows: Cardinal;
vLine: string;
vLineRowCount: Integer; //numbers of rows parsed in this line
vTempRowLengths: PRowLengthArray;
vRowBegin: PChar;
vLineEnd: PChar;
vRowEnd: PChar;
vRunner: PChar;
vRowMinEnd: PChar;
//
vStartRow: Integer; // first row of the line
vOldNextRow: Integer; // first row of the next line, before the change
cLine: Integer;
begin
// ****** First parse the new string using an auxiliar array *****
vLine := TSynEditStringList(Editor.Lines).ExpandedStrings[aIndex];
// Pre-allocate a buffer for rowlengths
vMaxNewRows := ((Length(vLine) - 1) div fMinRowLength) + 1;
vTempRowLengths := AllocMem(vMaxNewRows);
try
vLineRowCount := 0;
vRowBegin := PChar(vLine);
vRowEnd := vRowBegin + fMaxRowLength;
vLineEnd := vRowBegin + Length(vLine);
while vRowEnd < vLineEnd do
begin
//
if vRowEnd^ in [#32, #9] then
begin
repeat
Inc(vRowEnd);
until not(vRowEnd^ in [#32, #9]);
end
else begin
vRowMinEnd := vRowBegin + fMinRowLength;
vRunner := vRowEnd - 1;
while vRunner > vRowMinEnd do
begin
if vRunner^ in fBreakChars then
begin
vRowEnd := vRunner + 1;
break;
end;
Dec(vRunner);
end;
end;
// Check TRowLength overflow
if vRowEnd - vRowBegin > High(TRowLength) then
begin
vRowEnd := vRowBegin + High(TRowLength);
vRowMinEnd := vRowEnd - (High(TRowLength) mod Editor.TabWidth);
while (vRowEnd^ = #9) and (vRowEnd > vRowMinEnd) do
Dec(vRowEnd);
end;
{$IFDEF SYN_MBCSSUPPORT}
if StrByteType(vRowBegin, vRowEnd - vRowBegin) = mbTrailByte then
Dec(vRowEnd);
{$ENDIF}
// Finally store the rowlength
vTempRowLengths[vLineRowCount] := vRowEnd - vRowBegin;
//
Inc(vLineRowCount);
vRowBegin := vRowEnd;
Inc(vRowEnd, fMaxRowLength);
end;
if (vLineEnd > vRowBegin) or (Length(vLine) = 0) then
begin
vTempRowLengths[vLineRowCount] := vLineEnd - vRowBegin;
Inc(vLineRowCount);
end;
// ****** Then updates the main arrays ******
if aIndex = 0 then
vStartRow := 0
else
vStartRow := fLineOffsets[aIndex - 1];
vOldNextRow := fLineOffsets[aIndex];
Result := vLineRowCount - (vOldNextRow - vStartRow);
if Result <> 0 then
begin
// MoveRows depends on RowCount, so we need some special processing...
if Result > 0 then
begin
// ...if growing, update offsets (and thus RowCount) before rowlengths
GrowRows(RowCount + Result);
for cLine := aIndex to LineCount - 1 do
Inc(fLineOffsets[cLine], Result);
if vOldNextRow < RowCount - Result then
MoveRows(vOldNextRow, Result);
end
else begin
// ...if shrinking, update offsets after rowlengths
if vOldNextRow < RowCount then
MoveRows(vOldNextRow, Result);
for cLine := aIndex to LineCount - 1 do
Inc(fLineOffsets[cLine], Result);
end;
end;
Move(vTempRowLengths[0], fRowLengths[vStartRow], vLineRowCount * SizeOf(TRowLength));
finally
FreeMem(vTempRowLengths);
end;
end;
procedure TSynWordWrapPlugin.WrapLines;
var
cRow: Integer;
cLine: Integer;
vLine: string;
vMaxNewRows: Integer;
vRowBegin: PChar;
vLineEnd: PChar;
vRowEnd: PChar;
vRunner: PChar;
vRowMinEnd: PChar;
begin
if (Editor.Lines.Count = 0) or (fMaxRowLength <= 0) then
begin
SetEmpty;
Exit;
end;
GrowLines(Editor.Lines.Count);
GrowRows(Editor.Lines.Count);
//
cRow := 0;
for cLine := 0 to Editor.Lines.Count -1 do
begin
vLine := TSynEditStringList(Editor.Lines).ExpandedStrings[cLine];
//
vMaxNewRows := ((Length(vLine) - 1) div fMinRowLength) + 1;
GrowRows(cRow + vMaxNewRows);
//
vRowBegin := PChar(vLine);
vRowEnd := vRowBegin + fMaxRowLength;
vLineEnd := vRowBegin + Length(vLine);
while vRowEnd < vLineEnd do
begin
//
if vRowEnd^ in [#32, #9] then
begin
repeat
Inc(vRowEnd);
until not(vRowEnd^ in [#32, #9]);
end
else begin
vRowMinEnd := vRowBegin + fMinRowLength;
vRunner := vRowEnd - 1;
while vRunner > vRowMinEnd do
begin
if vRunner^ in fBreakChars then
begin
vRowEnd := vRunner + 1;
break;
end;
Dec(vRunner);
end;
end;
//
if vRowEnd - vRowBegin > High(TRowLength) then
begin
vRowEnd := vRowBegin + High(TRowLength);
vRowMinEnd := vRowEnd - (High(TRowLength) mod Editor.TabWidth);
while (vRowEnd^ = #9) and (vRowEnd > vRowMinEnd) do
Dec(vRowEnd);
end;
{$IFDEF SYN_MBCSSUPPORT}
if StrByteType(vRowBegin, vRowEnd - vRowBegin) = mbTrailByte then
Dec(vRowEnd);
{$ENDIF}
fRowLengths[cRow] := vRowEnd - vRowBegin;
//
Inc(cRow);
vRowBegin := vRowEnd;
Inc(vRowEnd, fMaxRowLength);
end;
if (vLineEnd > vRowBegin) or (Length(vLine) = 0) then
begin
fRowLengths[cRow] := vLineEnd - vRowBegin;
Inc(cRow);
end;
fLineOffsets[cLine] := cRow;
end;
fLineCount := Editor.Lines.Count;
end;
function TSynWordWrapPlugin.RowCount: integer;
begin
if LineCount > 0 then
Result := fLineOffsets[ LineCount -1 ]
else
Result := 0;
end;
procedure TSynWordWrapPlugin.SetEmpty;
begin
fLineCount := 0;
// free unsused memory
TrimArrays;
end;
procedure TSynWordWrapPlugin.TrimArrays;
begin
ReallocMem( fLineOffsets, LineCount * SizeOf(TRowIndex) );
fLineCapacity := LineCount;
ReallocMem( fRowLengths, RowCount * SizeOf(TRowLength) );
fRowCapacity := RowCount;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -