syneditwordwrap.pas
来自「一个mwEdit控件原码,比mwCuuEdit0.92a功能先进.」· PAS 代码 · 共 588 行 · 第 1/2 页
PAS
588 行
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.
if (RowCount - fLineOffsets[aIndex]) * aCount > RowCount * 5 then
begin
// This rudimentary optimization-wannabe tries to decide whether it's worth to
// use ReWrapLine() since this may move the tail rowlengths too many times.
WrapLines;
Result := RowCount - aIndex +1;
end
else begin
Result := 0;
for cLine := aIndex to aIndex + aCount -1 do
Inc( Result, ReWrapLine(cLine) );
end;
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 );
//
if (RowCount - fLineOffsets[aIndex]) * aCount > RowCount * 5 then
begin
WrapLines;
Result := RowCount - aIndex +1;
end
else begin
Result := 0;
for cLine := aIndex to aIndex + aCount -1 do
Inc( Result, ReWrapLine(cLine) );
end;
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;
// Finally store the rowlength
vTempRowLengths[ vLineRowCount ] := vRowEnd - vRowBegin;
//
Inc( vLineRowCount );
vRowBegin := vRowEnd;
Inc( vRowEnd, fMaxRowLength );
end;
vTempRowLengths[ vLineRowCount ] := vLineEnd - vRowBegin;
Inc( vLineRowCount );
// ****** 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;
fRowLengths[ cRow ] := vRowEnd - vRowBegin;
//
Inc( cRow );
vRowBegin := vRowEnd;
Inc( vRowEnd, fMaxRowLength );
end;
fRowLengths[ cRow ] := vLineEnd - vRowBegin;
Inc( cRow );
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 );
fLineCapacity := LineCount;
ReallocMem( fRowLengths, RowCount );
fRowCapacity := RowCount;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?