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

📄 rm_jveditor.pas

📁 这是一个功能强大
💻 PAS
📖 第 1 页 / 共 3 页
字号:
end;

procedure TJvEditorStrings.SetLockText(const Text: string);
begin
  JvEditor.LockUpdate;
  try
    inherited SetTextStr(Text)
  finally
    JvEditor.UnlockUpdate;
  end;
end;

procedure TJvEditorStrings.SetInternal(Index: Integer; const Value: string);
begin
  JvEditor.LockUpdate;
  try
    InternalPut(Index, Value);
  finally
    JvEditor.UnlockUpdate;
  end;
end;

function TJvEditorStrings.Add(const S: string): Integer;
begin
  Result := inherited Add(JvEditor.ExpandTabs(S));
end;

procedure TJvEditorStrings.Insert(Index: Integer; const S: string);
begin
  inherited Insert(Index, JvEditor.ExpandTabs(S));
  JvEditor.LineInserted(Index);
end;

procedure TJvEditorStrings.Delete(Index: Integer);
begin
  inherited Delete(Index);
  JvEditor.LineDeleted(Index);
end;

procedure TJvEditorStrings.Put(Index: Integer; const S: string);
var
  L: Integer;
begin
  if JvEditor.KeepTrailingBlanks then
    inherited Put(Index, S)
  else
  begin
    L := Length(S) - Length(TrimRight(S));
    if L = 0 then
      inherited Put(Index, S)
    else
    begin
      {--- UNDO ---}
      TJvDeleteTrailUndo.Create(JvEditor, Length(S), Index, Spaces(L));
      {--- /UNDO ---}
      inherited Put(Index, TrimRight(S));
    end;
  end;
end;

procedure TJvEditorStrings.ReLine;
var
  L: Integer;
  S: string;
  Y: Integer;
begin
  Y := JvEditor.CaretY; // save because Add('') changes CaretY
  JvEditor.LockUpdate;
  try
    BeginUpdate;
    try
      if Count = 0 then
        L := JvEditor.CaretX
      else
        L := Length(Strings[Count - 1]);
      while Y > Count - 1 do
      begin
        {--- UNDO ---}
        TJvReLineUndo.Create(JvEditor, L, JvEditor.CaretY, sLineBreak);
        {--- /UNDO ---}
        L := 0;
        Add('');
      end;
      JvEditor.CaretY := Y; // restore CaretY
      S := Strings[Y];
      if JvEditor.CaretX > Length(S) then
      begin
        L := JvEditor.CaretX - Length(S);
        {--- UNDO ---}
  //     TJvReLineUndo.Create(JvEditor, Length(S), Y, Spaces(L)); {disabled: moves the caret to wrong undo position }
        {--- /UNDO ---}
        inherited Put(Y, S + Spaces(L));
      end;
    finally
      EndUpdate;
    end;
  finally
    JvEditor.UnlockUpdate;
  end;
end;

procedure TJvEditorStrings.InternalPut(Index: Integer; const Value: string);
begin
  if JvEditor.KeepTrailingBlanks then
    inherited Put(Index, JvEditor.ExpandTabs(Value))
  else
    inherited Put(Index, TrimRight(JvEditor.ExpandTabs(Value)));
end;

{ delete text from [BegX..EndY] [BegY..EndY] all inclusive.
  BegX, EndX: [0..Max_X] }

procedure TJvEditorStrings.DeleteText(BegX, BegY, EndX, EndY: Integer);
var
  BegLine, EndLine: string;
  I, L: Integer;
begin
  if BegY < 0 then
  begin
    BegY := 0;
    BegX := 0;
  end;
  if BegY >= Count then
    Exit; // nothing to delete
  if EndY >= Count then
  begin
    EndY := Count - 1;
    EndX := MaxInt - 1;
  end;
  if BegX < 0 then
    BegX := 0;

  JvEditor.LockUpdate;
  BeginUpdate;
  try
    BegLine := Strings[BegY];
   // expand BegLine if necessary
    L := (BegX + 1) - Length(BegLine) - 1;
    if L > 0 then
      BegLine := BegLine + Spaces(L);

    EndLine := Strings[EndY];

    // delete lines between and end line
    for I := EndY downto BegY + 1 do
      Delete(I);

    System.Delete(BegLine, BegX + 1, MaxInt);
    System.Delete(EndLine, 1, EndX + 1);

    Internal[BegY] := BegLine + EndLine;
  finally
    EndUpdate;
    JvEditor.UnlockUpdate;
  end;
end;

{ insert text on X:[0..Max_X], Y }

procedure TJvEditorStrings.InsertText(X, Y: Integer; const Text: string);
var
  BegLine, EndLine: string;
  YStart: Integer;
  F, P: PChar;
  S, FirstLine: string;
  Len: Integer;
begin
  Inc(X); // increment for string functions
  if Y < 0 then
    Y := 0;
  while Y >= Count do
    Add('');

  BegLine := Strings[Y];
  EndLine := System.Copy(BegLine, X, MaxInt);
  System.Delete(BegLine, X, MaxInt);

  // line is too small -> expand it with spaces
  Len := Length(BegLine);
  if Len < X then
  begin
    SetLength(BegLine, X - 1);
    FillChar(BegLine[Len + 1], X - Len - 1, ' ');
  end;

  JvEditor.LockUpdate;
  BeginUpdate;
  try
    P := PChar(Text);
    F := P;
    while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
      Inc(P);

    SetString(S, F, P - F);

    YStart := Y;
    FirstLine := BegLine + S; // set Internal[YStart] later so we keep the trailing spaces for concat EndLine

    while P[0] <> #0 do
    begin
      if P[0] = Cr then
        Inc(P);
      if P[0] = Lf then
        Inc(P);
      F := P;

      while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
        Inc(P);
      SetString(S, F, P - F);
      Inc(Y);
      Insert(Y, S);
    end;

    if Y = YStart then
      Internal[YStart] := FirstLine + EndLine
    else
    begin
      Internal[YStart] := FirstLine;
      Internal[Y] := Strings[Y] + EndLine;
    end;
  finally
    EndUpdate;
    JvEditor.UnlockUpdate;
  end;
end;

{ delete column text from [BegX..EndY] [BegY..EndY] all inclusive.
  BegX, EndX: [0..Max_X] }

procedure TJvEditorStrings.DeleteColumnText(BegX, BegY, EndX, EndY: Integer);
var
  S: string;
  I: Integer;
begin
  if BegY < 0 then
  begin
    BegY := 0;
    BegX := 0;
  end;
  if BegY >= Count then
    Exit; // nothing to delete
  if EndY >= Count then
  begin
    EndY := Count - 1;
    EndX := MaxInt - 1;
  end;
  if BegX < 0 then
    BegX := 0;

  JvEditor.LockUpdate;
  BeginUpdate;
  try
    for I := BegY to EndY do
    begin
      S := JvEditor.FLines[I];
      System.Delete(S, BegX + 1, EndX - BegX + 1);
      JvEditor.FLines.Internal[I] := S;
    end;
  finally
    EndUpdate;
    JvEditor.UnlockUpdate;
  end;
end;

{ insert column text on X:[0..Max_X], Y }

procedure TJvEditorStrings.InsertColumnText(X, Y: Integer; const Text: string);
var
  S, Line: string;
  P, F: PChar;
  L: Integer;
begin
  Inc(X); // increment for string functions
  if Y < 0 then
    Y := 0;

  JvEditor.LockUpdate;
  BeginUpdate;
  try
    P := PChar(Text);
    F := P;
    while P[0] <> #0 do
    begin
      while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
        Inc(P);
      SetString(S, F, P - F);

      while Y >= Count do
        Add('');
      Line := Strings[Y];
      L := (X - 1) - Length(Line);
      if L > 0 then
        Line := Line + Spaces(L);
      System.Insert(S, Line, X);
      Internal[Y] := Line;

      if P[0] = Cr then
        Inc(P);
      if P[0] = Lf then
        Inc(P);
      F := P;
      Inc(Y);
    end;
  finally
    EndUpdate;
    JvEditor.UnlockUpdate;
  end;
end;

//=== { TJvCustomEditor } ====================================================

constructor TJvCustomEditor.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FLines := TJvEditorStrings.Create;
  FLines.FJvEditor := Self;
  FLines.OnChange := DoLinesChange;
  Completion := TJvCompletion.Create(Self);
end;

destructor TJvCustomEditor.Destroy;
begin
  FLines.Free;
  Completion.Free;
  inherited Destroy;
end;

procedure TJvCustomEditor.PaintLineText(Line: Integer; ColBeg, ColEnd: Integer;
  var ColPainted: Integer);
var
  Ch: string;
  iC, jC, SL, MX: Integer;
  R: TRect;
  S: string;
  LA: TLineAttr;
  jCStart, Len: Integer;
  MyDi: TDynIntArray;
begin
  with EditorClient do
  begin
    S := FLines[Line];

    Len := Max(Length(S), Max_X) + 1;
    if Len > Length(LineAttrs) then
      SetLength(LineAttrs, Len)
    else
    if Len + 128 < Length(LineAttrs) then
      SetLength(LineAttrs, Len);

    GetLineAttr(S, Line, ColBeg, ColEnd);

    {left line}
    if Canvas.Brush.Color <> LineAttrs[LeftCol + 1].BC then // change GDI object only if necessary
      Canvas.Brush.Color := LineAttrs[LeftCol + 1].BC;

    Canvas.FillRect(Bounds(EditorClient.Left, (Line - TopRow) *
      CellRect.Height, 1, CellRect.Height));
    {optimized, paint group of chars with identical attributes}
    SL := Length(S);
    MX := ColEnd;

    if Length(FMyDi) < MX then
    begin
      SetLength(MyDi, MX);
      for iC := 0 to High(MyDi) do
        MyDi[iC] := CellRect.Width;
     end
    else
      MyDi := FMyDi;

    while ColPainted < MX do
    begin
      with Canvas do
      begin
        iC := ColPainted + 1;
        LA := LineAttrs[iC];
        jC := iC + 1;
        if iC <= SL then
          Ch := S[iC]
        else
          Ch := ' ';
        jCStart := jC;
        while (jC <= MX + 1) and
          CompareMem(@LA, @LineAttrs[jC], SizeOf(LineAttrs[1])) do
            Inc(jC);
        Ch := Copy(S, jCStart - 1, jC - jCStart + 1);
        if jC > SL + 1 then
          Ch := Ch + Spaces(jC - SL - 1);

        if Brush.Color <> LA.BC then // change GDI object only if necessary
          Brush.Color := LA.BC;
        Font.Assign(FontCacheFind(LA));

        R := CalcCellRect(ColPainted - LeftCol, Line - TopRow);
        {bottom line}
        FillRect(Bounds(R.Left, R.Bottom - 1, CellRect.Width * Length(Ch), 1));

        TJvUnicodeCanvas(Canvas).ExtTextOut(R.Left, R.Top, [etoOpaque, etoClipped], nil, Ch, @MyDi[0]);
        ErrorHighlighting.PaintError(Canvas, ColPainted, Line, R, Length(Ch), MyDi);

        if LA.Border <> clNone then
        begin
          Pen.Color := LA.Border;
          R.Right := R.Left + CellRect.Width * Length(Ch);
          Dec(R.Left);
          Brush.Style := bsClear;
          Rectangle(R);
          Brush.Style := bsSolid;
        end;

        ColPainted := jC - 1;
      end;
    end;
  end;
end;

procedure TJvCustomEditor.GetLineAttr(var Str: string; Line, ColBeg, ColEnd: Integer);
var
  I: Integer;
begin
  if ColBeg < 0 then
    ColBeg := 0;
  if ColEnd > Max_X then
    ColEnd := Max_X;

  SetLength(LineAttrs, Max(Length(LineAttrs), Max_X + 1));

  LineAttrs[ColBeg].Style := Font.Style;
  LineAttrs[ColBeg].FC := Font.Color;
  LineAttrs[ColBeg].BC := Color;
  LineAttrs[ColBeg].Border := clNone;

{  for I := ColBeg + 1 to ColEnd do
    Move(LineAttrs[ColBeg], LineAttrs[I], SizeOf(LineAttrs[1]));}
  for I := ColBeg + 1 to ColEnd do
    LineAttrs[I] := LineAttrs[ColBeg];

  GetAttr(Line, ColBeg, ColEnd);
  if Assigned(FOnGetLineAttr) then
    FOnGetLineAttr(Self, Str, Line, LineAttrs);
  ChangeAttr(Line, ColBeg, ColEnd);
end;

function TJvCustomEditor.GetAnsiTextLine(Y: Integer; out Text: AnsiString): Boolean; 
begin
  if (Y >= 0) and (Y < Lines.Count) then
  begin
    Text := Lines[Y];
    Result := True;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -