diff --git a/funcext/tvclib/utslmemo.tsf b/funcext/tvclib/utslmemo.tsf index 27fbafd..1a272b4 100644 --- a/funcext/tvclib/utslmemo.tsf +++ b/funcext/tvclib/utslmemo.tsf @@ -202,8 +202,7 @@ type TTslMenoUndoList=class() //undolist fItems:TList; fLockCount:integer; fMaxUndoActions; - function GetCanUndo: - boolean; + function GetCanUndo():boolean; begin return fItems.length()>0; end @@ -218,8 +217,7 @@ type TTslMenoUndoList=class() //undolist end; end; end - function GetItemCount: - integer; + function GetItemCount():integer; begin return fItems.length(); end @@ -270,15 +268,13 @@ type TTslMenoUndoList=class() //undolist if fLockCount>0 then fLockCount--; return fLockCount; end - function PeekItem: - TSynEditUndoItem; + function PeekItem():TSynEditUndoItem; begin iLast := fItems.length()-1; if iLast >= 0 then return fItems[iLast]; return nil; end - function PopItem: - TSynEditUndoItem; + function PopItem():TSynEditUndoItem; begin if fLockCount>0 then return nil; if fItems.length()then return fItems.Pop(); diff --git a/funcext/tvclib/utslvclstdctl.tsf b/funcext/tvclib/utslvclstdctl.tsf index af6885e..01bb2f9 100644 --- a/funcext/tvclib/utslvclstdctl.tsf +++ b/funcext/tvclib/utslvclstdctl.tsf @@ -898,6 +898,11 @@ type teditable=class(TSLUIBASE) begin s1 := filterstring(s); if s1=fstring then return; + if fcanundo and (fundolist.locked<1) then + begin + fundolist.AddChange("del",1,-1,FString); + fundolist.AddChange("ins",1,-1,s1); + end FString := s1; if FCaretX=1 then begin @@ -972,7 +977,8 @@ type teditable=class(TSLUIBASE) X2 := FSelBegin+FSelLength-(FSelLength>0); b := min(x1,x2); e := min(max(x1,x2),length(FString)); - FString[b:e]:= ""; + if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]); + FString[b:e]:= ""; cx := max(1,min(x1,x2)); InitSel(); BeginUpDate(); @@ -1005,13 +1011,18 @@ type teditable=class(TSLUIBASE) len := length(FString); if FCaretX <= length(FString)then begin + b := FCaretX; if bytetype(FString,FCaretX)=1 then begin - FString[(FCaretX):(FCaretX+1)]:= ""; + e := FCaretX+1; + //FString[(FCaretX):(FCaretX+1)]:= ""; end else begin - FString[(FCaretX):(FCaretX)]:= ""; + e := b; + //FString[(FCaretX):(FCaretX)]:= ""; end + if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]); + FString[b:e] := ""; BeginUpDate(); InvalidateRect(nil,false); DeletePerfect(); @@ -1041,15 +1052,18 @@ type teditable=class(TSLUIBASE) if FCaretX>1 then begin cx := FCaretX; + e := FCaretX-1; if bytetype(FString,FCaretX-1)=2 then begin - FString[(FCaretX-2):(FCaretX-1)]:= ""; + b := FCaretX-2;//FString[(FCaretX-2):(FCaretX-1)]:= ""; cx -= 2; end else begin - FString[(FCaretX-1):(FCaretX-1)]:= ""; + b := FCaretX-1;//FString[(FCaretX-1):(FCaretX-1)]:= ""; cx--; - end + end + if fcanundo and (fundolist.locked<1) then fundolist.AddChange("del",b,e,FString[b:e]); + FString[b:e]:= ""; BeginUpDate(); MoveCaretTo(cx,0); DeletePerfect(); @@ -1169,6 +1183,9 @@ type teditable=class(TSLUIBASE) FCaretX := 1; FLeftCharCount := 0; //1; FFont := new Tcustomfont(); + fundolist := new tedolist(); + fredolist := new tedolist(); + fcanundo := true; end function InsertChar(c_); //插入 begin @@ -1205,6 +1222,7 @@ type teditable=class(TSLUIBASE) begin if(FFontWidth * (len+1))>(rc[2]-rc[0])then return; end + if fcanundo and (fundolist.locked<1) then fundolist.AddChange("ins",FCaretX,-1,c); if FCaretX=1 then begin FString := c+FString; @@ -1222,6 +1240,18 @@ type teditable=class(TSLUIBASE) function ExecuteCommand(cmd,pm);virtual; begin case cmd of + "canundo": + begin + fcanundo := pm; + end + "ecundo": + begin + undo(); + end + "ecredo": + begin + redo(); + end "echome": begin MoveCaretTo(1,pm); @@ -1332,6 +1362,15 @@ type teditable=class(TSLUIBASE) begin return FCaretX; end + "ecclear": + begin + fundolist.lock(); + selectall(); + dodelete(); + fundolist.clear(); + fredolist.clear(); + fundolist.lock(); + end end; end function GetEntryRect();virtual; @@ -1373,6 +1412,13 @@ type teditable=class(TSLUIBASE) begin ExecuteCommand("ecend",fsft); end + ord("Z"): + begin + if fctl then + begin + ExecuteCommand("ecundo",0); + end + end ord("C"): begin if fctl then @@ -1593,6 +1639,9 @@ type teditable=class(TSLUIBASE) property HasFocus read FSetFocused; property Focusedborder read FFocusBorder write FFocusBorder; private + fcanundo; + fredolist; + fundolist; FIsCaretShow; FKillFocus; FOnSetFocus; @@ -1608,6 +1657,56 @@ type teditable=class(TSLUIBASE) fselbkcolor; freadonlyColor; static FCopyer; + private + function undo(); + begin + if not fcanundo then return ; + it := fundolist.pop(); + if not it then return ; + fundolist.lock(); + try + doitem(it); + except + + end; + case it.freason of + "del":it.freason := "ins"; + "ins":it.freason := "del"; + end ; + fredolist.AddChange(it); + fundolist.unlock(); + //if not canundo then return ; + end + function redo(); + begin + if not fcanundo then return ; + it := fredolist.pop(); + if not it then return ; + doitem(it); + //if not canundo then return ; + end + function doitem(it); + begin + case it.freason of + "del": + begin + s := it.ftext; + b := it.FStart; + FCaretX := b; + InitSel(); + InsertChar(s); + end + "ins": + begin + s := it.ftext; + b := it.FStart; + FSelBegin := b; + FSelLength := length(s); + FCaretX := b+FSelLength; + dodelete(); + end + end ; + end end type tVirtualCalender=class(TSLUIBASE) {** @@ -2435,7 +2534,7 @@ type tthreeEntry=class(TCustomControl) if not ifarray(r)then return array(0,0,0,0); return r; end - function WMCHAR(o,e);override; + function WMCHAR(o,e):WM_CHAR;override; begin case e.char of "0" to "9":return inherited; @@ -5496,7 +5595,7 @@ type tcustomipaddr = class(TCustomControl) FPrev.ExecuteCommand("ecsel",array(10,1)); end end - function WMCHAR(o,e);override; + function WMCHAR(o,e):WM_CHAR;override; begin case e.char of "0" to "9" : @@ -5944,6 +6043,86 @@ type TTipWnd=class(TCustomControl) //tip private FSize; end +type tedoitem = class + function create(r,s,e,t); + begin + freason := r; + fstart := s; + fend := e; + ftext := t; + end + function clone(); + begin + return new tedoitem(freason,FStart,fend,ftext); + end + freason; //操作 + fstart; //开始位置 + fend; //截止位置 + ftext; //文本 +end +type tedolist = class() + public + function create(); + begin + flist := new tnumindexarray(); + flockct := 0; + end + function citem(r,s,e,t); + begin + return new tedoitem(r,s,e,t); + end + function lock(); + begin + flockct++; + end + function unlock(); + begin + if flockct>0 then + begin + flockct--; + end + return flockct; + end + function push(it); //弹出 + begin + if flockct then return 0; + if ifobj(it) then + begin + flist.push(it); + return 1; + end + end + function peak(); //获取 + begin + len := flist.length(); + if len>0 then + begin + return flist[len-1]; + end + return nil; + end + function pop(); + begin + if flockct=0 then + return flist.pop(); + return 0; + end + function clear(); + begin + if flockct then return ; + flist.splice(nil,nil,array()); + flockct := 0; + end + function AddChange(r,s,e,t); + begin + if ifobj(r) then push(r.clone()); + push(citem(r,s,e,t)); + end + property locked read flockct; + private + flockct; //计数 + flist; //链表 +end initialization {$ifdef linux}