📄 txtfind.asm
字号:
mov [otxFindLast],ax ;otxFindLast = offset of 0th line
jmp SHORT StartFromLast
; We are in SS_EXECUTE state. Map executor address in ax to opcode.
FBLGotExec:
xchg ax,bx ;executor address is in bx
mov ax,es:[bx-2] ;get opcode
DJMP jmp short FBLGotExecRet
;This value of CLINES_CACHE means in the QBI screen editor, a time
;consuming OtxOfLn search is performed every few page-up keys
;when the user is scrolling up through his file.
CLINES_CACHE EQU 60
DbPub FindBol
cProc FindBol,<NEAR>,<si,di,es>
localW cLnCache
localW oTxBolPrev
cBegin
DbChk Otx,ax
SetfDirect dl,FALSE ;turn off direct mode
; for TxtFindNextOp
mov [fLnNotIncl],NOT FALSE
xchg di,ax ;di = stopping text offset
mov ax,[otxFindLast] ;ax = oTxCur
mov dx,ax ;dx = oTxPrev
cmp di,ax
jb StartFromTop ;brif can't used cached value
cmp cx,[lnFindLast]
jb StartFromTop ;brif can't used cached value
sub cx,[lnFindLast] ;start search from last saved location
StartFromLast:
inc di ;Adjust otxMax since Lodsw in loop will
inc di ; advance 2 bytes past current opcode.
DJMP jcxz FindBolExit ;brif we've skipped enough lines (0)
mov [cLnCache],CLINES_CACHE+1 ;load count-down counter
push dx
push cx
call TxtSkipOp ;skip first opcode
xchg ax,si ;update oTxCur
GetSegAddr CODE ;ax = current address of CODE seg
push ax ;save addr of CODE seg
GetSegTxtCur ;[24]es = seg of curr txt table
push es
pop ds ;ds = seg addr of current text table
assumes ds,NOTHING
pop es ;es = seg addr of CODE seg
pop cx
pop dx
;*******************************************************************
; Register useage during loop
; DS - register points to text table until end-of-loop
; ES - points to CODE, where opcodes in execute state
; can be accessed
; SS - still points to DGROUP, so local vars can be accessed
; DI - otxMax (stop search if beyond otxMax)
; SI - otxCur (current otx of opcode we are searching)
; DX - otxBolCur (otx of last BOL encountered)
; CX - cLnMax (maximum number of BOLs to visit)
; BX - scratch
; AX - scratch
;*******************************************************************
FindBolLoop:
dec [cLnCache]
je UpdateCache ;brif time to save reference point
FindBolLoop1:
mov [oTxBolPrev],dx ;remember Bol of previous line
FBLInnerLoop:
lodsw ;ax = opcode/executor
cmp [txdCur.TXD_scanState],SS_EXECUTE ;is this table in execute?
DJMP je FBLGotExec ;brif so, map executor to opcode
FBLGotExecRet:
and ah,HIGH OPCODE_MASK ;upper bits sometimes used for operands
mov bx,ax ;bx = opcode
.errnz opBol
.errnz opBolSp-1
.errnz opBolInclude-opBolSp-1
.errnz opBolIncludeSp-opBolInclude-1
.errnz opBolLab-opBolIncludeSp-1
.errnz opBolLabSp-opBolLab-1
.errnz opBos-opBolLabSp-1
.errnz opBosSp-opBos-1
.errnz opEot-opBosSp-1
.errnz opEndProg-opEot-1
cmp ax,opEndProg ;is this opBol -> opEndProg?
jbe FBLGotHit ;brif so, we have an interesting opcode
FBLGotHitCont:
mov al,cs:[mpOpAtr_UNDONE + bx] ; al = #bytes in opcode
and ax,OPA_CntMask ;Isolate attribute count
.errnz OPA_CntMask AND 0FF00H
cmp al,OPA_CntMask ;is this a variable length opcode?
je FBLVarLenOpcode ;brif so
FBLVarLenRet:
add si,ax ;si points to next opcode
jmp short FBLInnerLoop ;go grab next opcode
FBLLoopCont:
loop FindBolLoop ;brif haven't reached line count limit
;We ran out of lines before we passed oTxMax. Return the otx of the
; last Bol encountered.
xchg ax,dx ;return oTxBolCur
jmp short FBLExit1
FindBolDone:
xchg ax,si ;return text offset of Bol in ax.
dec ax
dec ax ;back up to opcode
FBLExit1:
mov dx,[oTxBolPrev] ;return BOL of previous line
FindBolExit:
push ss
pop ds ;recover ds=DGROUP
; DbChk AtBosBol,ax ;sanity check on ret val
DbChk AtBosBol,dx ;sanity check on ret val
cEnd
;We have a variable length opcode. Grab and return count of bytes for opcode
;
FBLVarLenOpcode:
lodsw ;ax = # bytes of operands
inc ax ;round up to odd count as follows:
and al,-2 ; {0,1,2,3,4,...} => {1,3,3,5,5,...}
jmp short FBLVarLenRet
;This gets invoked every CLINES_CACHE times through FindBol's loop
;
UpdateCache:
mov [otxFindLast],dx ;save reference text offset
mov ax,CLINES_CACHE ;reload count-down counter
mov [cLnCache],ax
add [lnFindLast],ax ;update reference line number
jmp FindBolLoop1
;We have an interesting opcode. It is either an opBos/Bol variant, or
; it is an opEot, opEndProg
FBLGotHit:
cmp ax,opBos ;is it an opBol variant?
jb FBLGotBol ;brif so
cmp ax,opEot ;is it an opBos variant?
jb FBLGotHitCont ;brif so, continue search
;We must have either an opEot, or and opEndProg.
;If we found an opEndProg, we're done. If we found an opEot, it could only
;mean that we were called with an empty text table, and a search line > 0.
;In this case, we force the otxFound to 0.
;
jne FindBolDone ;it was an opEndProg
SetStartOtx ax ;oTxBol = first line
mov dx,ax ;oTxBolPrev = first line
jmp SHORT FindBolExit
FBLGotBol:
cmp si,di ;are we beyond oTxMax?
ja FindBolDone ;brif so
mov dx,si ;remember this BOL
dec dx
dec dx ;back up to opBol opcode
;Advance to next opcode
mov al,cs:[mpOpAtr_UNDONE + bx] ; al = #bytes in opcode
and ax,OPA_CntMask ;Isolate attribute count
.errnz OPA_CntMask AND 0FF00H
add si,ax ;si points to next opcode
cmp [fViewInclude],FALSE
FBLLoopCont_NE:
jne FBLLoopCont ;brif user wants to see INCLUDEd text
mov [fLnNotIncl],NOT FALSE ;assume line was not included
cmp bx,opBolInclude
jb FBLLoopCont ;brif line not included
cmp bx,opBolIncludeSp
ja FBLLoopCont_NE ;brif line not included
mov [fLnNotIncl],FALSE ;Line was included
jmp FindBolLoop1 ;dont count this line if it was included
assumes ds,DGROUP
;*************************************************************************
; TxtChkCache
; Purpose:
; This function is called whenever:
; - Text is editted in the text table (TxtChange, TxtDelete)
; It resets Watch and History, as well as calling TxtFlushCache if
; the editted pcode was prior to the previous cached value.
; Entry:
; si - oTx of lowest text offset affected by pcode movement
;
;*************************************************************************
;*************************************************************************
; TxtMoved
; Purpose:
; This function is called whenever:
; - Text is moved in the text table (TxtChange, TxtDelete, SsScan,
; SsDeScan)
; It resets Watch and History, as well as calling TxtFlushCache.
;
;*************************************************************************
;*************************************************************************
; TxtFlushCache
; Purpose:
; This function is called whenever:
; - The current text table changes (TxtActivate, TxtCurInit)
; It discards any static variables used to speed up searching
; of text tables.
;
;*************************************************************************
PUBLIC TxtChkCache
TxtChkCache PROC NEAR
cmp si,[otxFindLast] ;is affected pcode after cached otx?
jb TxtMoved ;brif not
;else txtmgr's cached otx still valid
call UiFlushCache ;tell User Interface to flush its cache
jmp SHORT TxtMovedNoFlush ;brif so, cached otx still valid
TxtChkCache ENDP
PUBLIC TxtMoved
TxtMoved PROC NEAR
call TxtFlushCache ;flush cached values
TxtMovedNoFlush:
test [mrsCur.MRS_flags2],FM2_NoPcode OR FM2_Include
jne NoPcode ;brif editing INCLUDE or DOCUMENT
cmp [grs.GRS_fDirect],FALSE
jne NoPcode ;brif editing direct mode stmt
call HistReset
call WatchMoved
NoPcode:
ret
TxtMoved ENDP
PUBLIC TxtFlushCache
TxtFlushCache PROC NEAR
mov ax,UNDEFINED
mov [lnFindLast],ax
mov [otxFindLast],ax
call UiFlushCache ;tell User Interface to flush its buffer
ret
TxtFlushCache ENDP
;*************************************************************************
; LnOfOtx
;
; Purpose:
; Given an offset within the current text table, return
; the physical line number of the line containing the text.
; Used for error reporting.
;
; Entry:
; parm1: ushort otx
;
; Exit:
; grs.fDirect is reset to FALSE
; AX = 0 relative line number for line containing the offset
; [fLnNotIncl] = zero if given line was an INCLUDEd line
;
; For example, if pcode contained:
; [0]opBol,[2]opStop,[4]opBol,[6]opStop,[8]opEndProg,[0A]opEot
; The following inputs would produce the following results:
; 0000 => 0000
; 0001 => 0000
; 0002 => 0000
; 0003 => 0000
; 0004 => 0001
; 0005 => 0001
; 0006 => 0001
; 0007 => 0001
; 0008 => fatal error (only checked in non-release versions)
;
;*************************************************************************
cProc LnOfOtx,<PUBLIC,FAR>
parmW otx
cBegin LnOfOtx
DbChk TxdCur ;perform sanity check on txdCur
mov cx,0FFFFH ;don't stop on line count
mov ax,[otx] ;stop when we've reached this otx
call FindBol ;search current text table
mov ax,0FFFFH
sub ax,cx ;ax = line number (0..n)
cEnd LnOfOtx
;*************************************************************************
; OtxOfLn
;
; Purpose:
; Given a physical line offset (0..n) within the current text
; table, return the byte offset into the text table for
; its opBol opcode.
;
; Entry:
; parm1: ushort lnSearch
;
; Exit:
; grs.fDirect is reset to FALSE
; AX = byte offset into text table
; [fLnNotIncl] = zero if given line was an INCLUDEd line
;
; For example, if pcode contained:
; [0]opBol,[2]opStop,[4]opBol,[6]opStop,[8]opEndProg,[0A]opEot
; The following inputs would produce the following results:
; 0000 => 0000
; 0001 => 0004
; 0002 => 0008
; 0003 => fatal error (only checked in non-release versions)
;
;*************************************************************************
cProc OtxOfLn,<PUBLIC,FAR>
parmW ln
cBegin
DbChk TxdCur ;perform sanity check on txdCur
mov cx,[ln] ;cx = # lines to skip
mov ax,[txdCur.TXD_bdlText_cbLogical] ;ax = offset to end-of-text
call FindBol ;ax = offset to bol
cEnd
;*************************************************************************
; OtxBolOfOtx
;
; Purpose:
; Given an offset within the current text table, return
; the text offset to the start of line.
; Entry:
; parm1: ushort otx
; Exit:
; grs.fDirect is reset to FALSE
; AX = byte offset into text table for line's opBol
; [fLnNotIncl] = zero if given line was an INCLUDEd line
;
; For example, if pcode contained:
; [0]opBol,[2]opStop,[4]opBol,[6]opStop,[8]opEndProg,[0A]opEot
; The following inputs would produce the following results:
; 0000 => 0000
; 0001 => 0000
; 0002 => 0000
; 0003 => 0000
; 0004 => 0004
; 0005 => 0004
; 0006 => 0004
; 0007 => 0004
; 0008 => fatal error (only checked in non-release versions)
;
;*************************************************************************
cProc OtxBolOfOtx,<PUBLIC,FAR>
parmW otx
cBegin OtxBolOfOtx
DbChk TxdCur ;perform sanity check on txdCur
mov cx,0FFFFH ;don't stop on line count
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -