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

📄 skyedit.pas

📁 SkyEdit是一个可用彩色语法来显示及编辑各种开发语言源代码的编辑器控件。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetSiteInfo;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseWheel;
    property OnMouseWheelDown;
    property OnMouseWheelUp;
    property OnResize;
    property OnSelectionChanged;     
    property OnStartDock;
    property OnStartDrag;
    property OnUnDock;
  end;

const
  //DIGIT = ['0'..'9'];
  //ALPHA = ['a'..'z', 'A'..'Z', '_'];

  LEFTBLANK = 2;  //绘制时左侧空白点数
  TOPBLANK  = 2;  //绘制时顶部空白点数


procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TSkyEdit]);
end;

function max(x, y: integer): integer;
begin
  if x > y then
    result := x
  else
    result := y;
end;

function min(x, y: integer): integer;
begin
  if x < y then
    result := x
  else
    result := y;
end;

{******************************************************************************
*                        以下是 TSkyUndoList 的实现                           *
******************************************************************************}
constructor TSkyUndoList.Create;
begin
  inherited Create;
  FList       := TList.Create;
  FMaxUndo    := 65536;
  FCurUndoTop := 0;
end;

destructor TSkyUndoList.Destroy;
begin
  RemoveAllChange();
  FList.Free;
  inherited Destroy;
end;

function TSkyUndoList.GetCanUndo: Integer;
begin
  FCanUndo := FCurUndoTop;
  Result   := FCanUndo;
end;

function TSkyUndoList.GetCanRedo: Integer;
begin
  FCanRedo := FList.Count - FCurUndoTop;
  Result   := FCanRedo;
end;

procedure TSkyUndoList.SetMaxUndo(const Value: Integer);
var
  i: Integer;
begin
  for i := FList.Count - 1 downto FCurUndoTop do
  begin            //一但有“撤消”加入,则清除所有Redo信息!
    RemoveChange(i);
  end;

  if Value > 0 then//MaxUndo > 0 ,即最小为 1
  begin
    if Value < FList.Count then
      for i := 0 to FList.Count - Value - 1 do
        RemoveChange(0);
    FMaxUndo := Value;
  end;
end;

procedure TSkyUndoList.SetCurUndoTop(const Value: Integer);
begin               //当前“撤消”栈顶指针( 1..FUndoList.Count )
  if Value < 0 then
    FCurUndoTop := 0
  else if Value > FList.Count then
    FCurUndoTop := FList.Count
  else
    FCurUndoTop := Value;
end;

procedure TSkyUndoList.RemoveChange(Index: Integer);
var                 //从“撤消”栈中删除一个元素
  pChg : PChangeRec;
begin
  if (Index >= 0) and (Index < FList.Count) then
  begin
    pChg := FList.Items[Index];
    try
      StrDispose(pChg^.ChangeStr);
      try
        FreeMem(pChg);
      except
        exit;
      end;
    except
      exit;
    end;
    Flist.Delete(Index);
  end;
end;

procedure TSkyUndoList.RemoveAllChange;
var
  i: Integer;
begin
  for i := FList.Count - 1 downto 0 do
    RemoveChange(i);
end;

procedure TSkyUndoList.AddChange(ChgMode: TChangeMode; ChgBegin, ChgEnd: TPoint;
                 ChgStr: PChar; bMerge: Boolean);
var                 //加入“撤消”
  pChg : PChangeRec;
  AChgMode: TChangeMode;
  sLastChg, sCurChg: String;

  procedure ClearRedo;
  var
    i: Integer;
  begin             //一但有“撤消”加入,则清除所有Redo信息!
    for i := FList.Count - 1 downto FCurUndoTop do
      RemoveChange(i);
  end;

  procedure RemoveAllOverMaxUndo;
  begin             //将超出Undo栈顶的删掉
    if FList.Count >= FMaxUndo then //RemoveChange(0); //2004.12.15
    begin                           //这里应该处理一下MultiBegin/End  2004.12.24
      if GetChange(0) <> cmMultiBegin then
        RemoveChange(0)
      else           //若是以cmMultiBegin开始的,则应删到cmMultiEnd为止
      begin
        while (FList.Count > 0) do
        begin
          AChgMode := GetChange(0); //栈底的TChangeMode
          RemoveChange(0);
          if AChgMode = cmMultiEnd then    //一直删到cmMultiEnd为止
            Break;
        end;
      end;
    end;
  end;

  function MergeChangeTop: Boolean;
  var
    idx: Integer;
    AChgBegin, AChgEnd: TPoint;

    function FindMatchChgMode(var idx: Integer; ChgMode: TChangeMode): Boolean;
    var                  //从当前Undo栈顶开始查找与ChgMode匹配的改变模式
      CurChgMode: TChangeMode;
    begin
      Result := False;
      repeat
        Dec(idx);
        CurChgMode := GetChange(idx);
      until (CurChgMode = ChgMode) or (CurChgMode = cmNone)
             or (CurChgMode = cmMultiBegin);
      if CurChgMode = ChgMode then
        Result := True;
    end;

  begin
    Result   := False;
    if FLastMerge then   //上一次是“合并”,本次才需“合并”
    begin
      idx      := FCurUndoTop - 1;
      AChgMode := GetChange(idx);
      if (AChgMode = ChgMode) and (ChgMode = cmInsert) then
      begin                    //对于 KeyPress.cmInsert -> ChangeStr = nil
        with PChangeRec(FList.Items[idx])^ do
        begin                  //以下只是针对“插入”时以行为单位进行简单合并
          if (ChangeEnd.Y = ChgBegin.Y) and (ChangeEnd.X = ChgBegin.X) then
          begin
            ChangeEnd := ChgEnd;
            Result    := True;
          end;
        end;
      end
      else if (AChgMode = cmMultiEnd) then
      begin
        if (FChgModeBuf = cmNone) and (ChgMode = cmInsert) then
        begin              //处理有选中文本时插入的情形(KeyPress插入) 2004.12.29
          if (GetChange(idx - 1, AChgBegin, AChgEnd) = cmInsert) then
            with PChangeRec(FList.Items[idx - 1])^ do
              if (ChangeEnd.Y = ChgBegin.Y) and (ChangeEnd.X = ChgBegin.X) then
              begin
                ChangeEnd := ChgEnd;
                with PChangeRec(FList.Items[idx])^ do
                begin      //必须调整上一次MultiEnd位置! 2004.12.29
                  ChangeBegin := ChgEnd;
                  ChangeEnd   := ChgEnd;
                end;
                Result    := True;
              end;
        end                //2004.12.29 以下目前只处理KeyPress中“改写”的情况
        else if (ChgMode = cmMultiBegin) then
        begin              //这里认为只有KeyPress中的MultiBegin/End才会合并
          Self.GetChange(idx, AChgBegin, AChgEnd);
          if (AChgEnd.Y = ChgBegin.Y) and (AChgEnd.X >= ChgBegin.X)
              and (AChgBegin.X <= ChgBegin.X) then
          begin            //只在紧跟上一次改变之后的“改写”才需在以下合并处理
            FChgModeBuf := ChgMode;
            Result      := True;
          end
          else
            FChgModeBuf := cmNone;
        end
        else if (FChgModeBuf = cmMultiBegin)
                 and ((ChgMode = cmMultiEnd)
                       or FindMatchChgMode(idx, ChgMode)) then
        begin
          if ChgMode = cmInsert then
          begin            //这里已不需检查,因MultiBegin已检查过
            with PChangeRec(FList.Items[idx])^ do
            begin
              ChangeEnd := ChgEnd;
              Result    := True;
            end;
          end
          else if ChgMode = cmDelete then
          begin
            with PChangeRec(FList.Items[idx])^ do
            begin          //这里已不需检查,因MultiBegin已检查过
              if (ChgBegin.X >= ChangeEnd.X)
                  or (ChgEnd.X > ChangeEnd.X) then
              begin        //如果有交叉或新改变位置紧跟在原改变位置之后
                sLastChg  := ChangeStr;
                sCurChg   := ChgStr;
                //删掉交叉部分的串(实际上是插入的一些空白字符) 2004.12.29
                Delete(sCurChg, 1, ChangeEnd.X - ChgBegin.X);
                StrDispose(ChangeStr);
                ChangeStr := StrNew(PChar(sLastChg + sCurChg));
              end;
              ChangeEnd := ChgEnd;
              Result    := True;
            end;
          end
          else if ChgMode = cmMultiEnd then
          begin
            with PChangeRec(FList.Items[idx])^ do
            begin          //这里已不需检查,因MultiBegin已检查过
              ChangeBegin := ChgBegin;
              ChangeEnd   := ChgEnd;
              Result      := True;
            end;
          end;
        end;
      end;
    end
    else
      FChgModeBuf := cmNone;
  end;

begin
  ClearRedo;
  RemoveAllOverMaxUndo;

  if not bMerge or not MergeChangeTop() then
  begin
    FLastMerge := bMerge;
    try
      GetMem(pChg,SizeOf(TChangeRec));
      try
        pChg^.ChangeStr := StrNew(ChgStr);
      except
        FreeMem(pChg);
        exit;
      end;
    except
      exit;
    end;
    pChg^.ChangeMode  := ChgMode;
    pChg^.ChangeBegin := ChgBegin;
    pChg^.ChangeEnd   := ChgEnd;
    FList.Add(pChg);
    CurUndoTop := FList.Count;  //重置“撤消”栈顶指针
  end
  else

⌨️ 快捷键说明

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