📄 txtmove.asm
字号:
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 + -