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

📄 txtmove.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	TITLE	txtmove.asm - Contains text manager's text movement functions

;======================================================================
; Module: txtmove.asm - Contains text manager's text movement functions
;
;	--------- --- ---- -- ---------- ----
;	COPYRIGHT (C) 1985 BY MICROSOFT, INC.
;	--------- --- ---- -- ---------- ----
;     
;
;=======================================================================*/

	.xlist
	include version.inc
	TXTMOVE_ASM = ON	;don't include EXTRNs defined in this file
	includeOnce architec
	includeOnce heap
	includeOnce conint			
	includeOnce context
	includeOnce opcontrl
	includeOnce opmin
	includeOnce optables
	includeOnce parser
	includeOnce pcode
	includeOnce rtps
	includeOnce scanner
	includeOnce txtint
	includeOnce txtmgr
	includeOnce util
	.list

assumes	ds,DATA
assumes	ss,DATA

sBegin	DATA

	externB b$errinfo		;defined by runtime - extended Out of
					; memory error code.

sEnd	DATA

sBegin	CP
assumes	cs,CP


;*************************************************************************
; TxtCurInit()
;
; Purpose:
;	Sets the txdCur.xxx fields to reflect a newly initialized text table.
;	It is called by the context manager functions MrsMake, PrsMake.
;	An empty text table is allocated for the text descriptor.
;	If we're creating a PRS and not loading, the text table contains:
;	   opBol opStSub/opStFunc(cntEos,oPrs,oTyp,0)
;	   opBol opStEndProc
;	   opEndProg
;	   opEot
;	else the text table contains
;	   opEndProg
;	   opEot
;
; Entry:
;	Assumes no txdCur is active
;
; Exit:
;	All fields of the global structure 'txdCur' are filled in.
;	If no error occurred, returns Non-Zero else FALSE
;	NOTE: If an error occurs, this function guarentees caller need not
;	deallocate txdCur.bdlText.
;	Condition codes set based on value in ax
;	
;*************************************************************************
cProc	TxtCurInit,<PUBLIC,NODATA,NEAR>,<di>
	localW	tempBuf
cBegin
	and	[grs.GRS_flags],NOT FG_allSsExecute
	call	TxtFlushCache		;can't depend on cached text offsets
	PUSHI	ax,<dataOffset txdCur>
	PUSHI	ax,<SIZE TXD/2>		;bx = #words in txtCur
	call	FillUndef		;fill whole struct with UNDEFINED
	PUSHI	ax,<dataOFFSET txdCur.TXD_bdlText>
	PUSHI	ax,CB_EMPTY_TEXT	;ask for minimal req'd size initially.
					;  Important that we ask for no more,
					;  so that when we discard an existing
					;  mrs, we can always find enough room
					;  to create an empty unnamed mrs again.
	PUSHBDL_TYPE  pgtypEBPcode,ax	; pass sb type for EB version
	call	BdlAlloc
	or	ax,ax
	jne	GotMem
	jmp	short TxtCurExit	;return FALSE if out-of-memory
GotMem:
	mov	[txdCur.TXD_scanState],SS_PARSE
	sub	ax,ax
	mov	[txdCur.TXD_cLines],ax
	mov	[txdCur.TXD_cLinesIncl],ax
	mov	[txdCur.TXD_flags],al
	mov	ax,[grs.GRS_oPrsCur]
	inc	ax			;test for UNDEFINED
	jne	TxtCurPrs		;brif we're creating a prs text table
	or	[txdCur.TXD_flags],FTX_mrs
					;remember that this is a module txt tbl
	test	[mrsCur.MRS_flags2],FM2_NoPcode OR FM2_Include
	je	TxtCurExitGood		;brif not an $INCLUDE or Document mrs
	inc	[txdCur.TXD_scanState]	;convert SS_PARSE to SS_RUDE
	.errnz SS_RUDE - SS_PARSE - 1
	jmp	SHORT TxtCurExitGood

TxtCurPrs:
	;If module is in SS_RUDE state, and we're creating a procedure,
	;put that procedure in SS_RUDE state as well.
	
	mov	al,[mrsCur.MRS_txd.TXD_scanState]
	cmp	al,SS_RUDE
	jb	TxtCurExitGood		; brif module's not in SS_RUDE state
	mov	[txdCur.TXD_scanState],al
TxtCurExitGood:
	call	TxtInitTxtTbl		;set up initial txt table.
DbAssertRel ax,ne,0,CP,<TxtCurInit:Unexpected OM error>
; ax should be non-zero after call to TxtInitTxtTbl
TxtCurExit:
	or	ax,ax			;set condition codes for caller
cEnd

;*************************************************************************
; TxtInitTxtTbl()
;
; Purpose:
;	Added with revision [26].
;	Inits a minium txt table.  Inserts opEndProg and opEot.
; Entry:
;	txdCur defines current text table.
; Exit:
;	AX = 0 if OM. Condition codes set via or ax,ax
;
;*************************************************************************
cProc	TxtInitTxtTbl,<NEAR>,<DI>
cBegin
	PUSHI	ax,<dataOFFSET txdCur.TXD_bdlText>
					;pass adr of bdl for text table
	PUSHI	ax,CB_EMPTY_TEXT	;make sure we have enough free
	call	BdlCheckFree		;ax = result
	or	ax,ax
	je	TITT_Exit		;brif out of memory

;We use GetSeg to get the seg addr of the text table here so that
;sbCur does not need to preserved to create a text table.
	GETSEG	es,[txdCur.TXD_bdlText_seg],,<SIZE,LOAD> ;es points to text tbl
	SetStartOtx di			;otxInsert = start of text
	mov	ax,opEndProg
	stosw
	mov	ax,opEot
	stosw
.erre CB_EMPTY_TEXT - 4 EQ StartOtx	;empty text table has 4 bytes of pcode
	mov	[txdCur.TXD_bdlText_cbLogical],CB_EMPTY_TEXT
.erre	opEot
TITT_Exit:
	or	ax,ax
cEnd

;*************************************************************************
; TxtDelAllFar()
;
; Purpose:
;	Added with revision [26].
;	Deletes all text in the module, leaving a minimal text table.
;	Called by the user interface to remove all text from a text table,
;	leaving opEndProg and opEot.
; Entry:
;	grs.oMrsCur indicates current module
;	grs.oMrsPrs indicates current procedure (UNDEFINED if none)
; Exit:
;	none.
;
;*************************************************************************
PUBLIC	TxtDelAll
TxtDelAll PROC FAR
	call	TxtDeleteAll		;delete all text in the text
					; table except endprog and eot
	call	ChkAllUndefPrsSaveRs	;discard any prs's with last
					;reference deleted by delete
	ret
TxtDelAll ENDP

;*************************************************************************
; TxtDeleteAll()
;
; Purpose:
;	Deletes all text in the module, leaving a minimal text table.
; Entry:
;	grs.oMrsCur indicates current module
;	grs.oMrsPrs indicates current procedure (UNDEFINED if none)
; Exit:
;	none.
;
;*************************************************************************
PUBLIC	TxtDeleteAll
TxtDeleteAll PROC NEAR
	cmp	[txdCur.TXD_bdlText_cbLogical],CB_EMPTY_TEXT
	jbe	EmptyText		;brif text table is empty (TxtLoad
					;    does this for temp text tables)
					;Don't need delete OpEndProg OpEot
	test	[grs.GRS_flagsDir],FDIR_new
	je	NotNewStmt		;brif NewStmt is not active (speed
					; optimization - NEW takes forever
					; if this is not done)
	mov	[prsCur.PRS_otxDef],UNDEFINED
					;if prs is active, this will cause
					;PrsDiscard to call PrsFree
					;if mrs is active, this has no effect
	jmp	SHORT EmptyText

NotNewStmt:
	call	TxtModified		;descan current text table to SS_PARSE
					;this may alter txdCur.bdlText.cbLogical
					;It also sets FM2_Modified
	PUSHI	ax,StartOtx		;delete from start of text table
	mov	ax,[txdCur.TXD_bdlText_cbLogical]
	dec	ax
	dec	ax
	push	ax			;entire text table is being discarded
	call	TxtDelete		;ax = return code
					;Note: TxtDelete may cause TxtActivate/
					; TxtDeactivate to be called via
					; ForEachPrsInMrs, but before it
					; returns, it restores whatever text
					; table was active when it was called.

	call	TxtInitTxtTbl		;set up default txt table
DbAssertRel ax,ne,0,CP,<TxtDeleteAll: unexpected OM error>
EmptyText:
	ret
TxtDeleteAll ENDP

;*************************************************************************
; TxtDiscard()
;
; Purpose:
;	Takes any text-mgr action needed before a text table is discarded
;	by the context manager.  This includes prompting the user with
;	"This action will prevent CONT" if appropriate.
;
; Sequence of events for NewStmt, as it affects text tables:
; NewStmt calls MrsDiscard for each mrs in system which has file associated
;    with it (i.e. doesn't call it for command window or scrap mrs's)
; MrsDiscard calls PrsDiscard for each prs which has a text table and
;    whose PRS_oMrs field = mrs.  It then calls TxtDiscard to discard
;    module's text table.
; PrsDiscard calls TxtDiscard to discard the procedure's text table.
;
; Entry:
;	grs.oMrsCur indicates current module
;	grs.oMrsPrs indicates current procedure (UNDEFINED if none)
; Exit:
;	if no error, returns 0
;
;*************************************************************************
PUBLIC	TxtDiscard
TxtDiscard PROC NEAR
	;NOTE - we can't call DbChk TxdCur here because txtload.c calls
	; it for a temporary buffer where it would fail.
	

	call	TxtDeleteAll		;delete all text in text table

; If we are discarding a prs, make sure that the defining ref deleted
; flag gets set.  TxtDelete won't do this if the there are no references
; to the prs, and the prs has a text table.  This could happen if the
; SUB or FUNCTION statment is a reparse, and no other reference exists.

	test	[txdCur.TXD_flags],FTX_Mrs  ; are we discarding an PRS
	jne	MrsTxtTbl		; text table?  brif so
	or	[flagsTM],FTM_PrsDefDeleted 
MrsTxtTbl:
	PUSHI	ax,<dataOFFSET txdCur.TXD_bdlText>
					;pass ptr to bdl structure for txt tbl
	call	BdlFree			;release it (note that this sets
					; bdlText_status to NOT_OWNER in txdCur)
	inc	ax			;return 'no-error' (0) result
	ret
TxtDiscard ENDP

;*************************************************************************
; TxtActivate()
;
; Purpose:
;	Sets the txdCur.xxx fields to reflect the current text table.
;	This involves copying the txd struct from mrsCur or the global Rs table.
;	If grs.oPrsCur is UNDEFINED, or represents a procedure with
;	no text table (i.e. for a DECLARE or DEF FN prs), then the
;	copy is from the mrsCur.txd, else it is from the global Rs table.
;	It is called by the context manager functions MrsActivate & PrsActivate
;	NOTE: Callers can (and do) depend on this function causing
;	      NO heap movement.
;
; Entry:
;	grs.oMrsCur indicates current module
;	grs.oMrsPrs indicates current procedure (UNDEFINED if none)
;
; Exit:
;	All fields of the global structure 'txdCur' are copied from
;	mrsCur or the global Rs table.
;	
;*************************************************************************
PUBLIC	TxtActivate
TxtActivate PROC NEAR
	call	TxtFlushCache		;can't depend on cached text offsets
	sub	al,al			;copy mrs/prs -> txd
	sub	cx,cx			;assume we're activating module txt tbl
	mov	bx,[grs.GRS_oPrsCur]
	inc	bx
	.errnz	UNDEFINED - 0FFFFH
	jz	TxtAct1			;brif no prs is active

	dec	bx
	RS_BASE add,bx			; bx pointer to start of prs in table
	GETRS_SEG es,cx,<SIZE,LOAD>	;[3]
	mov	cx,PTRRS[bx.PRS_txd.TXD_bdlText_status] 
	sub	cx,NOT_OWNER		;cx = 0 if prs doesn't own a text table
	jmp	SHORT TxtAct1
TxtActivate ENDP

;*************************************************************************
; TxtDeactivate()
;
; Purpose:
;	Copies the txdCur.xxx fields to the txd struct in mrsCur or the
;	appropriate place in the global Rs table.
;	If grs.oPrsCur is UNDEFINED, or represents a procedure with
;	no text table (i.e. for a DECLARE or DEF FN prs), then the
;	copy is to the mrsCur.txd, else it is to the global Rs table.
;	It is called by the context manager functions MrsDeactivate &
;	PrsDeactivate.
;	NOTE: Callers can (and do) depend on this function causing
;	      NO heap movement.
;
; Entry:
;	grs.oMrsCur indicates current module
;	grs.oMrsPrs indicates current procedure (UNDEFINED if none)
;
; Exit:
;	All fields of the global structure 'txdCur' are copied to mrsCur
;	or the global Rs table.
;	
;*************************************************************************
PUBLIC	TxtDeactivate
TxtDeactivate PROC NEAR

	DbChk	TxdCur			;perform sanity check on txdCur

	;eliminate any free space at the end of current text table,
	;so if far heap mgr needs space, the only places it needs to
	;look are static structures txdCur and mrsCur.  This is smaller
	;code than having to walk the far heap.  If it becomes a performance
	;bottleneck, we'll have to delete this and walk the far heap.
	
	PUSHI	ax,<DATAOFFSET txdCur.TXD_bdlText>
	call	BdlTrim

	mov	al,1			;tell common code we're deactivating
	sub	cx,cx
	test	[txdCur.TXD_flags],FTX_mrs
	jne	TxtAct1			;brif deactivating module text table
	dec	cx			;we're deactivating prs text table

;This code is shared between TxtActivate and TxtDeactivate
; al = 0 for Activate, non-zero for Deactivate
; cx = 0 if activating/deactivating module text table
;    = non-zero for procedure text table
;
TxtAct1:
assumes ds,nothing			
     DbAssertRel grs.GRS_oMrsCur,ne,UNDEFINED,CP,<Txt[De]Activate mrs=UNDEFINED>
	push	si			;save caller's si/di
	push	di
	push	ss			
	pop	es			; assume DGROUP->DGROUP copy
	mov	di,dataOFFSET mrsCur.MRS_txd  ; di -> current mrs's txd struct
	jcxz	NoPrs			      ;brif text table not for prsCur
	GETRS_SEG es,di,<SPEED,LOAD>	;[3] assume we're deactivating
	mov	di,[grs.GRS_oPrsCur]	
	RS_BASE add,di			
	add	di,PRS_txd		; di -> current prs's txd struct
     DbAssertRel grs.GRS_oPrsCur,ne,UNDEFINED,CP,<Txt[De]Activate prs=UNDEFINED>
NoPrs:
	mov	si,dataOFFSET txdCur	; si -> cur text tbl descriptor
	or	al,al
	jnz	DoTheCopy		; brif we're deactivating
	xchg	si,di			; we're activating
DoTheCopy:
.errnz	(SIZE TXD) MOD 2		;block copy assumes even # of bytes
	mov	cx,(SIZE TXD) SHR 1	;cx = # words to copy

	push	si			;pass src BdlChgOwner
	push	di			;pass dst to BdlChgOwner
	rep movsw			; do the copy
	call	BdlChgOwner		
	pop	di			;restore caller's si/di
	pop	si
assumes ds,DATA 			
	ret
TxtDeactivate ENDP

;*************************************************************************
; TxtMoveUp(otxSrcLow, cbIns)
;
; Purpose:
;	Move a block of text from a low address to a higher address

⌨️ 快捷键说明

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