📄 skyedit.pas
字号:
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 + -