📄 undo.asm
字号:
;撤消与重做
_PushUndo proto:DWORD ,:DWORD ,:DWORD ,:DWORD
_realloc_undo proto
_InitUndo proto
_UndoEnd proto
_Undo proto
_SetScroll proto
UNDO_INPUT=1
UNDO_DELETE=2
UNDO_INSERT=3
UNDO_REPLACE=4
UNDOINFO struct
lpAddress dd ?
bValue db ?
lpMem dd ?
dwSize dd ?;删除或插入的字节
dwByteToMove dd ?;删除或插入总共要移动的字节(=文件大小-开始选择-dwSize)
mode db ?
UNDOINFO ends
.const
UndoLevel =(sizeof UNDOINFO)*100
.data?
lpUndo dd ?;head
lpUndoPos dd ?;trai
dwUndoSize dd ?;count
;----------------------------------------------
;--------------------------------------------
.code
;-----------------------------------
;初始化撤消区域,在程序启动和打开文件时调用
_InitUndo proc
.if lpUndo
call _UndoEnd
.endif
__alloc UndoLevel
mov lpUndo,eax
mov lpUndoPos,eax
mov dwUndoSize,UndoLevel
invoke EnableMenuItem,hMenu,IDM_EDIT_UNDO,MF_GRAYED
ret
_InitUndo endp
;------------------------------
;释放撤消占用的内存
_UndoEnd proc uses edi
mov edi,lpUndoPos
.while edi>lpUndo
sub edi,sizeof UNDOINFO
assume edi:ptr UNDOINFO
.if [edi].lpMem
__free [edi].lpMem
.endif
assume edi:nothing
.endw
__free lpUndo
ret
_UndoEnd endp
;-----------------------------
;保存撤消
;参数
;lpAddress:当前地址
;nMode:类型
;Bytes:插入或删除的字节数(只有插入或删除时才用到此参数)
;nValue:插入值(只有插入时才用到此参数,如果它<=255,则是一个绝对的值,否则它是一个数据的地址
;返回值:无
_PushUndo proc lpAddress,nMode,Bytes,nValue
pushad
invoke EnableMenuItem,hMenu,IDM_EDIT_UNDO,MF_ENABLED
mov ebx,lpUndoPos
assume ebx:ptr UNDOINFO
mov eax,Bytes
mov [ebx].dwSize,eax
mov eax,nMode
mov [ebx].mode,al
mov eax,lpAddress
mov [ebx].lpAddress,eax
.if [ebx].mode==UNDO_INPUT;普通输入
mov al,[eax]
mov [ebx].bValue,al
mov [ebx].dwSize,1
.elseif [ebx].mode==UNDO_DELETE;删除
__alloc Bytes
.if eax
mov [ebx].lpMem,eax
;将原来的内容复制到缓冲区
invoke RtlMoveMemory,eax,lpAddress,[ebx].dwSize
mov eax,Bytes
mov ecx,dwFileSize
sub ecx,dwBlockStart
sub ecx,eax
mov [ebx].dwByteToMove,ecx
sub dwFileSize,eax
sub lpMemFileEnd,eax
;将后面的内容向前移动
mov esi,dwBlockEnd
add esi,lpMemFile
inc esi
mov edi,lpAddress
rep movsb
mov eax,dwBlockStart
.if eax>=dwFileSize
mov eax,dwFileSize
dec eax
.endif
mov dwBlockStart,eax
mov dwBlockEnd,eax
mov dwCurPos,eax
invoke _SetScroll
.else
call _ShowError
.endif
.elseif [ebx].mode==UNDO_INSERT;插入
;;;插入由于增加了文件的体积,须重新申请内存
mov eax,dwBlockStart
mov [ebx].lpAddress,eax;只保留相对地址.由于重新申请内存的原因,绝对地址是不行的
mov edi,dwFileSize
add edi,Bytes
invoke GlobalSize,lpMemFile
.if edi>eax
mov eax,edi
add eax,EXTRASIZE
__alloc eax
.if eax
push eax
invoke RtlMoveMemory,eax,lpMemFile,dwFileSize
__free lpMemFile
pop lpMemFile
.endif
.endif
mov eax,lpMemFile
mov lpMemFileEnd,eax
mov esi,eax
mov esi,dwBlockStart
add esi,eax;选择的开始
mov eax,edi
mov edi,esi;为下面的rep movsb
mov ecx,dwFileSize
sub ecx,dwBlockStart
mov dwFileSize,eax
add lpMemFileEnd,eax
;将当前的内容向后移动
m2m [ebx].dwSize,Bytes
mov [ebx].dwByteToMove,ecx
invoke _movmemf,esi,Bytes,ecx
mov eax,nValue
mov ecx,Bytes
.if eax>255;大于255,是指针
invoke RtlMoveMemory,edi,eax,ecx
.else
rep stosb
.endif
mov eax,dwBlockStart
mov dwCurPos,eax
add eax,Bytes
dec eax
mov dwBlockEnd,eax
invoke _SetScroll
.elseif [ebx].mode==UNDO_REPLACE;替换
__alloc [ebx].dwSize
.if eax
mov [ebx].lpMem,eax
invoke RtlMoveMemory,eax, [ebx].lpAddress,[ebx].dwSize
.else
call _ShowError
.endif
.endif
or FLAG_ALL,FLAG_FILECHANGE
call _ReDraw
invoke _realloc_undo
add lpUndoPos,sizeof UNDOINFO
_ret_:
assume ebx:nothing
popad
ret
_PushUndo endp
;------------------------------------------------
;重新申请撤消缓冲区
_realloc_undo proc uses ebx
mov eax,__sub2(__add2(dwUndoSize,lpUndo),sizeof UNDOINFO)
.if lpUndoPos>=eax
__alloc __add2(dwUndoSize,UndoLevel);重新申请一块内存
.if eax
push eax
invoke RtlMoveMemory,eax,lpUndo,dwUndoSize;把原来的内容复制过去
__free lpUndo
pop ebx
mov lpUndoPos,__sub2(lpUndoPos,lpUndo);取原来的相对位置
mov lpUndo,ebx
add lpUndoPos,ebx
add dwUndoSize,UndoLevel
.else
call _ShowError
.endif
.endif
ret
_realloc_undo endp
;-----------------------------------
_Undo proc
pushad
sub lpUndoPos,sizeof UNDOINFO
mov ebx,lpUndoPos
assume ebx:ptr UNDOINFO
.if [ebx].mode==UNDO_INPUT;撤消输入
mov al,[ebx].bValue
mov edi,[ebx].lpAddress
stosb
.elseif [ebx].mode==UNDO_DELETE;撤消删除
mov eax,[ebx].dwSize
add dwFileSize,eax
add lpMemFileEnd,eax
;将原有的内容向后移
invoke _movmemf,[ebx].lpAddress,[ebx].dwSize,[ebx].dwByteToMove
;插入被撤消的内容
mov ecx,[ebx].dwSize
mov esi,[ebx].lpMem
mov edi,[ebx].lpAddress
rep movsb
;释放内存
__free [ebx].lpMem
mov [ebx].lpMem,0
invoke _SetScroll
.elseif [ebx].mode==UNDO_INSERT;撤消插入
;将后面的内容向前移动
mov esi,lpMemFile
mov eax,[ebx].lpAddress;lpAddress只是一个相对地址(删除或输入时是绝对地址)
push eax
add esi,eax
mov edi,esi
add esi,[ebx].dwSize
mov ecx,[ebx].dwByteToMove
rep movsb
mov eax,[ebx].dwSize
sub dwFileSize,eax
sub lpMemFileEnd,eax
invoke _SetScroll
pop eax
jmp @f
.elseif [ebx].mode==UNDO_REPLACE;替换
invoke RtlMoveMemory,[ebx].lpAddress,[ebx].lpMem,[ebx].dwSize
__free [ebx].lpMem
mov [ebx].lpMem,0
.endif
mov eax,[ebx].lpAddress
sub eax,lpMemFile
@@:
invoke _SetPos,eax
assume ebx:nothing
or FLAG_ALL,FLAG_FILECHANGE
call _ReDraw
mov eax,lpUndo
.if lpUndoPos==eax
invoke EnableMenuItem,hMenu,IDM_EDIT_UNDO,MF_GRAYED
.endif
popad
ret
_Undo endp
;--------------------------------------------------------
;删除或插入后要重新设定滚动条
_SetScroll proc
invoke GetScrollPos,hWnd,SB_VERT
push eax
mov eax,dwFileSize
shr eax,4
dec eax
mov g_TotalLine,eax
invoke SetScrollRange,hWnd,SB_VERT ,0,eax,TRUE
pop eax
.if eax>g_TotalLine
invoke _SetPos,0
.endif
ret
_SetScroll endp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -