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

📄 txtmgr.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
					; a new defining ref otw set to 0
	mov	[uprs.UPRS_fPrsDelFound],dx ;set fPrsDelFound to 0 if we
					; are searching for a defining ref
	mov	dx,[grs.GRS_oPrsCur]	;set up global specifying which proc
	mov	[uprs.UPRS_oPrsDel],dx	;  we are searching for references to
	push	cx			;preserve condition flag

	;Note that we search even text mrs's because the reference
	;to the prs may be within an INCLUDE mrs.  It is tempting to
	;make INCLUDE mrs's be FM2_NoPcode mrs's, but doing so would
	;prevent the ability to select the 'View/Include File' menu
	;item when an INCLUDE mrs is active, because the $INCLUDE
	;lines would not have been parsed.
	
	;This leads to the situation that an INCLUDE mrs can be
	;the owner of a prs.  This keeps the prs from being deleted until
	;all references to the prs are gone.  However, we must also insure
	;that the include mrs does not become an owner of a prs when other
	;"stronger" definitions exist.	Therefore, all prs references from
	;an include mrs will be treated as the "weakest" possible owners.
	
	mov	bx,CPOFFSET TryToDefPrs
	mov	al,FE_PcodeMrs+FE_TextMrs+FE_CallMrs+FE_PcodePrs+FE_SaveRs
	call	ForEachCP
	cmp	[uprs.UPRS_fNoRefSameMod],FALSE	
	je	GotRefInSameModule	;brif another ref in module found

;We have not found another reference to the Prs in the module from which
;the ref was deleted. Clear the NMSP_sub name table bit of the sub's oNam
;in that module so that it can be used now as a variable name.
	push	[grs.GRS_oRsCur]	;save current oRs for reactivation
	push	[uprs.UPRS_oMrsRefDel]	
	call	MrsActivateCP		;activate the module 
	cCall	FieldsOfPrs,<si>	;ax = oNam of proc
	xchg	bx,ax			;pass bx = oNam of proc
	mov	al,NMSP_SUB		;pass al = flag to clear
	call	ResetONamMask		;clear sub bit of oNam of Mrs
	call	RsActivateCP		;reactivate the Rs we were searching
GotRefInSameModule:			
	pop	cx			;cx = 0 iff otxDef is defined
	jcxz	J1_FreeAllUndef_Cont	;brif otxDef is defined - i.e. we
					; were only searching for another
					; ref in module of deletion
	cmp	[uprs.UPRS_fPrsDelFound],0 ;was a new defining reference found
	je	ChkDeletePrs		;brif didn't find new "defining" ref

	;found new "defining" reference
	
	call	SetPrsDefn		;parms are in static struct dprs
J1_FreeAllUndef_Cont:			
	jmp	FreeAllUndef_Cont 	;[37] go on to next prs

ChkDeletePrs:
	;Prs has no "defining" reference
	;If prs has no text table, release it via PrsFree
	;  By the time this function has been called by PrsDiscard,
	;    any text table that this prs might have owned will have
	;    been released.
	
	test	[txdCur.TXD_flags],FTX_mrs ;does this prs have a text table?
	je	J1_FreeAllUndef_Cont	; brif so, will eventually be freed
					; by PrsDiscard

	call	PrsFree 		;free the prs
	DbAssertRel [grs.GRS_oPrsCur],z,UNDEFINED,CP,<FreeAllUndefinedPrs err>
	jmp	FreeAllUndef_Cont2 	;[37] go on to look for next prs,
					 ; starting from last prs that
					 ; we did not free ...
FreeAllUndef_Exit:			
	pop	di			
	pop	si			
	and	WORD PTR[flagsTm],NOT(FTM_PrsDefDeleted+FTM2_PrsRefDeleted*100h)
					;all Prs entries are clean
	ret
FreeAllUndefinedPrs ENDP

;**************************************************************
; UndefPrs(ax:oPrsDelete)
; Purpose:
;	This function is called whenever the "defining"
;	text reference to a prs is deleted.  It clears
;	the prs definition flags and sets prs.otxDef to
;	undefined.
;
; NOTE: The caller is responsible for calling ChkAllUndefPrs
;	to search for a new defining reference, or release
;	the prs entry if no more references to the prs exist.
; NOTE: Some callers expect no heap movement from this routine.
;
; Entry:
;	ax is the oPrs whose reference is being deleted
;
; Exit:
;	prs.otxDef = UNDEFINED
;	prs definition flags are cleared.
;	restores caller's active register set.
;
;**************************************************************
PUBLIC	UndefPrs
UndefPrs PROC NEAR
	push	[grs.GRS_oRsCur]	;save caller's active register set

	push	ax			;pass to PrsActivateCP
	call	PrsActivateCP		;activate prs which may be freed
	or	[flagsTm],FTM_PrsDefDeleted ;we have deleted a defining reference
	mov	[prsCur.PRS_otxDef],UNDEFINED ;remember that current "defining"
					;reference has been deleted
	Msk EQU NOT (FP_DEFINED OR FP_DECLARED OR FP_CDECL)
	and	[prsCur.PRS_flags],Msk	;turn off these flag bits
					;SetPrsDefn will be called to turn
					;one or more back on if another ref
					;is found in the pcode
	call	RsActivateCP		;activate caller's register set
					; oRs parm is already on stack
	ret
UndefPrs ENDP

;**************************************************************
; boolean UpdatePrs()
; Purpose:
;	This is called after text has been inserted into, or deleted
;	from any text table.  It is called for each prs which could be
;	declared in this text table (even if by CALL <compiled sub>),
;	If the prs's "defining" reference is in this text table:
;	   If the reference was deleted by the edit:
;	      Set its Otx field to UNDEFINED
;		a new defining reference will be searched for at completion
;		of the current edit operation
;	   else if the "defining" reference was moved by the edit:
;	      its otx field is updated
;	This function will flag many prs entries if the
;	deleted text included many DECLAREs, where the DECLARE was the
;	only remaining reference.
;
;	NOTE: to drastically improve text edit performance, this routine
;	gets called by ForEachPrsInPlaceCP, which marches through the
;	prs table without activating the PRS.  Thus, this routine MUST
;	NOT cause heap movement which would invalidate the pointer
;	used to march the prs table.
;
; Entry:
;	si = ptr to prs entry being examined
;	uprs.UPRS_oRsEdit = text table in which edit occurred
;	uprs.UPRS_otxEdit = text offset where text was inserted/deleted
;	uprs.UPRS_cbDel = number of bytes deleted
;	uprs.UPRS_cbIns = number of bytes inserted
;
;**************************************************************
DbPub	UpdatePrs
UpdatePrs PROC NEAR
	GETRS_SEG es,dx,<SIZE,LOAD>	;[11]
	mov	dx,PTRRS[si.PRS_otxDef] ; dx = text offset to prs's "defining"
					; reference
	inc	dx			;test for UNDEFINED
	je	UpExit			;brif prs has no references
	dec	dx			;restore dx = otxDef
	mov	ax,PTRRS[si.PRS_oRsDef] 
	cmp	BPTRRS[si.PRS_procType],PT_DEFFN 
	jne	UpdNotDefFn		;brif not a DEF FN
	mov	ax,PTRRS[si.PRS_oMrs]	; DEF FNs live in a module's text table
UpdNotDefFn:
	cmp	ax,[uprs.UPRS_oRsEdit]
	jne	UpExit			;brif not text table being edited
	;prs is currently defined by reference in edited text table
	mov	ax,[uprs.UPRS_otxEdit]
	cmp	dx,ax
	jb	UpExit			;brif reference unaffected by edit
	add	ax,[uprs.UPRS_cbDel]
	cmp	ax,dx
	jbe	UpMoved			;brif defining ref moved by edit

	;Defining reference has been deleted.
	;Mark Prs to indicate that defining reference has been deleted.
	
	mov	ax,si		;ax = ptr to prs entry
	RS_BASE sub,ax		;ax=oPrs for entry, parm to UndefPrs
	call	UndefPrs	;Mark Prs as "defining" reference as
				;deleted
	jmp	SHORT UpExit

;defining reference has been moved up or down in memory
UpMoved:
	mov	ax,[uprs.UPRS_cbIns]
	sub	ax,[uprs.UPRS_cbDel]
	add	PTRRS[si.PRS_otxDef],ax ; update otx based on edit
UpExit:
	or	ax,sp		; return ax != 0 and NZ
	ret
UpdatePrs ENDP



;**************************************************************
; boolean NEAR TxtDelete(otxDelFirst, otxDelLast)
; Purpose:
;	Delete some text from the current text table.
;	Doesn't update linked lists if ASCII load is active.
;
; NOTE:
;	If a Prs's "defining" reference is being deleted, this function
;	will cause the prs to be marked as UNDEFINED.  It is up to
;	the caller to insure that orphaned "New" defining references
;	the prs do not exist by calling ChkAllUndefPrs if the possibility
;	of deleting a "defining" reference has occurred during the
;	edit operation.
;
; Entry:
;	Same as for TxtChange:
;
; Exit:
;	Same as for TxtChange
;	[cForDel] = 1 + number of FOR statements deleted
;	[cForStepDel] = 1 + number of FOR...STEP statements deleted
;	Condition codes are set based on value in ax
;
;**************************************************************
cProc	TxtDelete,<PUBLIC,NEAR,NODATA>,<si,di>
	parmW	otxDelFirst
	parmW	otxDelLast
	localW	otxNext
	localW	otxTop
	localW	otxBottom
	localW	oTyp
	localW	cbDel
cBegin
 DbAssertRelB [txdCur.TXD_scanState],ne,SS_EXECUTE,CP,<TxtDelete err 1>
	DbChk	Otx,otxDelFirst		;error if > txdCur.bdlText.cbLogical
	DbChk	Otx,otxDelLast		;error if > txdCur.bdlText.cbLogical
	DbAssertRel [otxDelFirst],be,[otxDelLast],CP,<TxtDelete err 2>
	mov	di,[otxDelFirst]
	mov	al,[bigEditState]
	cmp	al,BIG_EDIT_CANCEL
	jne	DelNoCancel
	jmp	DelGoodExit		;backout of BigEdit if user CANCELed

DelNoCancel:
	cmp	[txdCur.TXD_SCANSTATE],SS_SUBRUDE 
	jne	DelNotSubRude		;	
	jmp	DelNoThreads		;don't need to examine text before
					; deletion if no oPrs's in code
DelNotSubRude:				;	
	cmp	al,BIG_EDIT_FALSE
	jne	DelInBigEdit		;brif in a BigEdit
	mov	[cForDel],1
	mov	[cForStepDel],1
DelInBigEdit:

;-------------------------------------------------------------------
;Examine the block of pcode being deleted opcode by
;opcode, looking for a RUDE EDIT
;   
	mov	cx,[otxDelLast]
	sub	cx,di			;compute cb to be deleted
	mov	[cbDel],cx
	jcxz	DelPreDone		;brif no text to delete, destroy scrap

	test	[mrsCur.MRS_flags2],FM2_Include OR FM2_NoPcode
	jne	DelNotTextMrs		;brif document/include file is active

	cmp	[b$cNonQBIFrames],0	;nonzero when non-QBI frames are on 
					; the stack.  Any edit at this point
					; could invalidate return addresses on 
					; the stack.  At this point we have 
					; decided to askcantcont instead of 
					; trying to fix up the return addresses
					; on the stack.
					;are non qbi return addresses on stack?
	jne	DelAskCantCont		;brif so, check for possible back out
DelNotTextMrs:
	test	[mrsCur.MRS_flags2],FM2_Include
	je	DelNotIncl1		;brif not editing an include file
DelAskCantCont:
	call	AskCantCont_CP		;ask user "Want to back out?"
	je	J1_DelBackOut		;return FALSE if user wants to back out
DelNotIncl1:
	push	di			;pass [otxDelFirst]
	PUSHI	ax,<CODEOFFSET tOpPreDel>
	call	TxtFindOp		;find 1st opcode of interest

;ax = offset to 1st opcode of interest
;dl = [txtFindIndex]
DelPreLoop:
	cmp	ax,[otxDelLast]
	jae	DelPreDone		;brif no significant opcodes were in
					;deleted range
	xchg	si,ax			;si = text offset to current opcode
	;opBol and opBolLab are in the PREDEL list to keep us from unnecessarily
	; searching all the way to opEot for innocuous edits of large "simple"
	; txt tables.  This can significantly speed up simple edits.
	
	cmp	dl,PREDEL_BolMax	;is this just a Bol?
	jbe	J1_DelPreNext		;brif so, search for next opcode.

	cmp	dl,PREDEL_IncludeMax
	jbe	DelInclude		;brif INCLUDE (or $INCLUDE [QB4])

	;It must be PREDEL_rudeMin or greater - rude edit
	push	dx			;save txtfindindex in case AskRudeEdit
					;calls TxtFind
	call	AskRudeEdit		;see if user wants to back out of edit
	pop	ax			;al = txtfindindex
	je	J1_DelBackOut		;return FALSE if user wants to
					; back out of edit
	FloadActive			;don't descan if Loading
	jne	DelPreNext
	cmp	al,PREDEL_opStDefType
	jne	DelPreNext		;brif not DEFINT..DEFSTR stmt
	call	SystemDescanCP		;implicit parms in DECLARE, SUB,
					; FUNCTION stmts need to be rechecked
					; by the scanner
DelPreNext:
	push	si
	PUSHI	ax,<CODEOFFSET tOpPreDel>
	call	TxtFindNextOp		;find next opcode of interest
	jmp	SHORT DelPreLoop

DelInclude:
	push	si			;pass otx
	call	OtxNoInclude		;ax = otx to opBol/opEot for next line
					; which has no $INCLUDE
	cmp	ax,[otxDelLast] 	;is end of $INCLUDE pcode beyond
					; requested delete?
	jbe	J1_DelPreNext		;brif not
	mov	[otxDelLast],ax		;delete all included lines as well
	sub	ax,di			;ax = new cbDel
	mov	[cbDel],ax
J1_DelPreNext:
	jmp	SHORT DelPreNext


J1_DelBackOut:
	jmp	DelBackOut		;return FALSE - user wants to
					; back out of edit

;-------------------------------------------------------------------
; If fFillScrap and bdTxtScrap is empty,
;    fFillScrap = FALSE
;    copy deleted text to bdTxtScrap
;    otxScrap = otxDelFirst
; If cbBigIns > 0, cbBigIns -= cbDel
;
;Note that cbDel may actually be zero but that we still create the scrap
;because we may subsequently be called during a big edit with fFillScrap
;TRUE but we don't want to fill the scrap.

DelPreDone:
	cmp	[fFillScrap],FALSE
	je	DelNoCopy		;brif no need to copy text to scrap
	cmp	[bdlTxtScrap.BDL_status],NOT_OWNER	
	jne	DelNoCopy		;brif scrap is already in use
	mov	[fFillScrap],FALSE	;reset one-shot flip-flop
	mov	[otxScrap],di		;remember text offset of deleted text

;  CALL TxtCopyScrap(otxDelFirst, 0, cbDel, FALSE)	[9]
	push	di			;push otxDelFirst
	xor	ax,ax			
	push	ax			;offset of where to copy into Scrap
	push	[cbDel]
	push	ax			;push FALSE meaning don't delete text
	call	TxtCopyScrap		;ax = 0 if out of memory
	jnz	CopiedOK		;brif buffer allocated successfully

	call	AskRudeEdit		;Give user a chance to back out of edit
					; if CONT is currently possible.
	je	J1_DelBackOut		;return FALSE if user wants to
					; back out of edit
	jmp	SHORT DelNoCopy

CopiedOK:

;-------------------------------------------------------------------
;NOTE: At this point, the user CANNOT back out of the edit.
;      All actions from this point on are irreversible.
;
;Examine the block of pcode being deleted opcode by
;opcode, taking special action for each opcode of interest.
;   
; Register usage for loop: si = otxCur, di = otxDelFirst

⌨️ 快捷键说明

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