⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syneditwordwrap.pas

📁 一个非常好的c++编译器
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -