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

📄 undo.asm

📁 一个十六进制编辑器源代码,cool!
💻 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 + -