📄 uiedit.asm
字号:
; Entry:
; ax = otx to next opcode to be executed by interpreter, or
; FFFF if next opcode is not in this text table.
; si = otx to start of line to be listed.
; di = ptr to buffer descriptor for destination.
; Exit:
; ax = number of bytes listed (as returned by ListLine)
; dx = column offset that corresponds to entry's ax
;
;**************************************************************************
ListAxSiDi PROC NEAR
mov [otxLsCursor],ax
cCall ListLine,<si,di> ; cbLine = ListLine(otx, pbd)
ret
ListAxSiDi ENDP
;**************************************************************************
; ushort cbGetLineBuf(hbuf, ln, cbMax, szDst)
; Purpose:
; Called by TextWin's editor, even when the current buffer has been
; modified and the line needs to be refreshed. This routine gets
; the specified ASCII line of text even it is the current line (i.e. UNDO).
;
; Entry:
; hbuf - buffer handle.
; ln - line to copy
; cbMax - Max number of character to copy to buffer.
; szDst - where to put the zero terminated line
; grs.otxCONT = text offset to next instruction to be executed
;
; Exit:
; if grs.otxCONT points into line being listed:
; colStmtStart = column of start of next statement
; colStmtEnd = column of end of next statement
; else
; colStmtStart = colStmtEnd = UNDEFINED
; return number of characters put in buffer (excluding terminating zero)
; If out-of-memory, sets [uierr] to ER_OM and returns 0
;
;**************************************************************************
cProc cbGetLineBuf,<PUBLIC,FAR>,<si,di>
parmW hbuf
parmW ln
parmW cbMax
parmDP szDst
cBegin
;Caller can only call us to list to 1 of 2 buffers:
; ps.bdpSrc or bdEMScratch, see which it is
; The reason twin passes an absolute pointer is because twin is used
; by other products that have static buffers.
mov di,DATAOFFSET ps.PS_bdpSrc
mov ax,[szDst]
cmp ax,[di.BD_pb]
je GotBdPtr ; brif ps.bdpSrc is our buffer
mov di,DATAOFFSET bdEMScratch
DbAssertRel ax,e,[di.BD_pb],UI,<cbGetLineBuf called with bad pointer>
;di = ptr to output buffer descriptor
GotBdPtr:
mov bx,[hbuf]
cmp bx,hbufHelp ; Check for help buffer
jne @F ; if not, skip ahead
mov ax,WM_HELPLINE ; message to send
mov bx,OFFSET DGROUP:wndHelp ; window to send to
cCall SendMessage,<bx,ax,[ln],[szDst],[cbMax]>
inc [fWndHelp] ; Set flag for GetLineAttrs
jmp GlbExit
@@:
mov [fWndHelp],0 ; make sure flag is reset
call ActivateHbuf
call fDocumentBuf ; Is this a large document buffer?
jz GLB_NotDocument ; brif not, let txtmgr handle it
push [mrsCur.MRS_pDocumentBuf]
push ln
push cbMax
push szDst
call S_cbGetLineBuf ; Get line from document buffer
jmp SHORT GlbExit
GLB_NotDocument:
; [otxGetNext] is a cached otx for line [lnGetNext].
; See if we can use it.
mov si,[otxGetNext]
mov ax,[ln]
mov cx,[lnGetNext]
inc ax ;cache the otx for [ln]+1
mov [lnGetNext],ax
dec ax
jcxz RefreshCache ;brif cached otx is invalid
cmp ax,cx
je GotOtx
; Cached otx was no good, we have to search for the otx.
;
RefreshCache:
cCall OtxOfLn,<ax>
xchg si,ax ; mov si,ax
;Save cached otx for next call
GotOtx:
mov [otxLnLast],si
; ListLine checks to see if otxLsCursor is in the current line, and if so
; it returns dx=the equivalent column for the opcode at that otx.
; If the current text table is the `active text table' (i.e. the text table
; containing the next statement to be executed), then otxLsCursor is setup
; appropriately. grs.oRsContTxtTbl gets set whenever grs.oRsCONT gets set.
; The only time it is different then grs.oRsCONT is when grs.oRsCONT is
; for a DEF FN, in which case, this gets set to the oRs for the module
; that contains the DEF FN.
;
mov ax,UNDEFINED ;assume line doesn't contain next stmt
; to be executed by interpreter
mov [colStmtStart],ax
mov [colStmtEnd],ax
xchg dx,ax ;dx = UNDEFINED
mov ax,[grs.GRS_oRsContTxtTbl]
cmp ax,[grs.GRS_oRsCur]
jne ListTheLine ;brif this isn't the oRs with next
; stmt to exec
mov ax,[grs.GRS_otxCONT]
inc ax ;test for UNDEFINED
jz ListTheLine ;brif grs.GRS_otxCONT == UNDEFINED
xchg dx,ax ;dx = otxCONT
dec dx ;undo above inc
;Don't be tempted to enable this... Keep the comment around
; as a reminder, because it is very tempting...
; This causes bug where if you edit the line with
; the current instruction, afterward, it looks like the
; previous line contains the next instruction.
; Maybe fix this another way, or always keep a NOP after
; opStSub, opStFunction, opStDefFn, opStStop
;;;;Set dx to otxCONT - 1, so if STOP and BreakPoint after DEF FN,
;;;; SUB, or FUNCTION will highlight the STOPPED stmt.
;;;;je ListTheLine ;brif grs.GRS_otxCONT == 0
;;;;dec dx
;dx = new otxLsCursor, si = otx to list, di = bdDestination
ListTheLine:
xchg ax,dx ; ax = new otxLsCursor
call ListAxSiDi ; cbLine = ListLine(otx, pbd)
inc ax ; test for UNDEFINED
je GlbOmErr ; return 0 if out-of-memory
dec ax ; restore ax = cbLine
push ax ; save cbLine (return value)
mov ax,[otxListNext] ; cache this value for next time
mov [otxGetNext],ax
inc dx ; test for UNDEFINED
je NotOnLine ; brif line doesn't contain next stmt
;Since we know this line contains next stmt to be executed,
;call ListLine twice more to find column offset for start and
;end of stmt, LineAttr can highlight the statement.
push [otxLsCursor]
call OtxBosOfOtx ; ax = otx for next stmt's bos
call ListAxSiDi ; cbLine = ListLine(otx, pbd)
; since this line was just listed,
; we are assured not out-of-memory
mov [colStmtStart],dx
inc dx
je NotOnLine
push [otxLsCursor] ; push otx arg.
call OtxBosNext ; ax = otx for next stmt's eos
call ListAxSiDi ; cbLine = ListLine(otx, pbd)
; since this line was just listed,
; we are assured not out-of-memory
mov [colStmtEnd],dx
inc dx
jne NotOnLine ; brif not UNDEFINED
dec dx ; dx = UNDEFINED
mov [colStmtStart],dx ; if colStmtEnd is UNDEFINED,
; so is colStmtStart
NotOnLine:
pop ax ; restore ax = cbLine (return value)
GlbExit:
cEnd
GlbOmErr:
call SetUiErrOm ; report error in msg loop
jmp SHORT GlbExit ; return ax=0
;**************************************************************************
; LineAttr(attrDefault)
; Purpose:
; Returns an array discribing the screen attributes for the last line
; fetched by cbGetLineBuf.
;
; Entry:
; attrDefault is the screen attribute to use for non-standout text.
; colStmtStart and colStmtEnd are as set by last call to cbGetLineBuf.
;
; Exit:
; returns pointer to array of LineAttr's.
; Each LineAttr consists of a count (cb) and an attribute (attr)
; attr is the attribute to be used for the next cb characters in the line.
; The array is terminated with an attr of 0xffff
; cb may be zero.
; If cb is 0xffff then attr is used for the rest of the line.
;
;**************************************************************************
cProc GetLineAttrs,<PUBLIC,FAR>,<si,di>
parmW attrDefault
cBegin
cmp [fWndHelp],0 ; Is being called for help window
je @F
mov [fWndHelp],0 ; Clear fWndHelp
mov ax,WM_HELPATTR ; message to send
cCall SendHelpMsg,<ax,ax> ; Send message to help system
jmp short AttrEnd
@@:
mov si,[attrDefault]
mov di,dataOFFSET rgLineAttr
cCall fCodeWnd
jz UseDefaultAttrs ;brif DOCUMENT text table
cmp [fLsIncluded],0
je NotIncluded
mov si,isaIncludeFileHilite
NotIncluded:
cCall fBpSet,<otxLnLast>
or ax,ax
je NoBpSet
mov si,isaBreakpoint
NoBpSet:
mov ax,[colStmtStart]
mov dx,[colStmtEnd]
inc ax ;test for UNDEFINED
je UseDefaultAttrs
inc dx ;test for UNDEFINED
je UseDefaultAttrs
dec ax ;ax = [colStmtStart]
;dx = [colStmtEnd] + 1
; Ahh, this line has the current statement on it.
; We must setup so that it gets highlighted properly
; ax = [colStmtStart], dx = [colStmtEnd]
;
mov [di.LA_cb],ax
mov [di.LA_attr],si
sub dx,ax ;dx = [colStmtEnd]+1-[colStmtStart]
mov ax,isaCurBreakpoint
cmp si,isaBreakpoint
je GotCurBp ;brif current stmt has breakpoint too
mov ax,isaCurStmt
GotCurBp:
mov [di + (size LINEATTR) + LA_cb],dx
mov [di + (size LINEATTR) + LA_attr],ax
mov ax,UNDEFINED
mov [di + (2*(size LINEATTR)) + LA_cb],ax
mov [di + (2*(size LINEATTR)) + LA_attr],si
mov [di + (3*(size LINEATTR)) + LA_attr],ax
jmp short GLA_End
UseDefaultAttrs:
mov ax,UNDEFINED
mov [di + LA_cb],ax
mov [di + LA_attr],si
mov [di + (size LINEATTR) + LA_attr],ax
GLA_End:
xchg ax,di ;return ax = &rgLineAttr
AttrEnd:
cEnd
;**************************************************************************
; StartBigEdit
; Purpose:
; Called by the Edit Mgr at the start of some operation which results
; multiple calls to InsertLineBuf/ReplaceLineBuf/DeleteLinesBuf.
; Examples include multi-line-paste/cut/copy, line-split, line-join.
;
; Entry:
;
; Exit:
;**************************************************************************
cProc StartBigEdit,<PUBLIC,FAR>
cBegin
cCall TxtStartBigEdit
cEnd
;**************************************************************************
; EndBigEdit
; Purpose:
; Called by the Edit Mgr at the end of some operation which results
; multiple calls to InsertLineBuf/ReplaceLineBuf/DeleteLinesBuf.
; Since during a BIG EDIT, all lines are emitted within opReParse
; operands, and not really parsed to pcode until TxtEndBigEdit,
; syntax errors may be discovered during TxtEndBigEdit().
;
; Exit:
; if error encountered, uierr is set to standard error code
;
;**************************************************************************
cProc EndBigEdit,<PUBLIC,FAR>
cBegin
cCall TxtEndBigEdit ;ax = non-zero if serious error
or ax,ax
je EndBigEdit_End
mov [uierr],ax
EndBigEdit_End:
cEnd
;**************************************************************************
; InsertBufInBuf()
; Purpose:
; Insert the contents of 1 buffer (usually the scrap) into another buffer
;
; Entry:
; hbufDst - buffer to insert other buffer into.
; lnDst - line before which the buffer is to be inserted.
; hbufSrc - the buffer the be inserted.
;
; Exit:
; returns zero if out-of-memory, non-zero if success
;
;**************************************************************************
cProc InsertBufInBuf,<PUBLIC,FAR>,<si,di>
parmW hbufDst
parmW lnDst
parmW hbufSrc
cBegin
call StartBigEdit ;so we don't stop inserting just
; because of a syntax error
mov bx,[hbufDst]
call ModifyAndGrab
call fDocumentBuf ; Is this a large document buffer
jz IBIB_NotDocument ; brif not, let txtmgr handle it
push [mrsCur.MRS_pDocumentBuf]
push lnDst
mov bx,hbufSrc ; bx = oPrs
and bh,7Fh ; mask off bit saying it is PRS.
RS_BASE add,bx
push [bx.MRS_pDocumentBuf]
call S_InsertBufInBuf
jmp SHORT IBIB_TestRetVal
IBIB_NotDocument:
push [lnDst]
call oTxOfLn ;get oTxInsert for destination buf
push ax ;pass oTxInsert
push [hBufSrc] ;pass src hBuf
call TxtPaste ;insert src buffer at insertion point
IBIB_TestRetVal:
or ax,ax ;Out of memory
jne IBIB_NotOm ;brif not out of memory
IBIB_OM:
call SetUiErrOm ;set out of memory error
IBIB_NotOm:
call EndBigEdit ;destination text table is active
sub ax,ax ;prepare to return 0 (error)
cmp [uierr],ax
jne IBIB_Done ;brif got an error
dec ax ;return non-zero (success)
IBIB_Done:
push ax
mov ax,[hbufDst]
call UnGrab ;free space reserved by ModifyAndGrab
pop ax
cEnd
;**************************************************************************
; ushort near hbufScrap()
; Purpose:
; Return the handle for the Scrap buffer, allocating the buffer if necessary.
;
; Exit:
; If out-of-memory, returns NULL
;
;**************************************************************************
cProc hbufScrap,<PUBLIC,FAR>
localV sdName,<size sd>
cBegin
mov ax,[hbufOfScrap]
cmp ax,UNDEFINED
jne hbufScrap_End
; Make a text table (the name is unimportant, but cbName must be non-zero -
; otherwise it is the UNTITLED module), so use the 1 byte string starting
; at address 1 as the name of the scrap.
lea bx,sdName
mov [bx.SD_pb],DATAOFFSET hbufOfScrap
;pb -> FF (impossible mrs name)
mov [bx.SD_cb],1
push bx ;pass &sdName
PUSHI ax,RS_scrap ;rsType
cCall RsMake ;ax = oRs of scrap
mov [hbufOfScrap],ax
mov [rsNew],UNDEFINED ;don't tell WnReset to display
; scrap in a list window
DbAssertRel ax,ne,0,UI,<hbufScrap oRs==0>
hbufScrap_End:
cEnd
;**************************************************************************
; UiDelAll
; Purpose:
; Delete all text from a specified text table
; Entry:
; bx = hbuf
;
;**************************************************************************
cProc UiDelAll,<NEAR>
cBegin
call ActivateHbuf ;activate text table bx
call TxtDelAll ;delete all text in the text
; table except endprog and eot
call fDocumentBuf ; is this a large document
jz DelAllExit ; brif not, all done
push [mrsCur.MRS_pDocumentBuf]
call FreeBuf ; Release buffer
call NewBuf ; get a new one
mov [mrsCur.MRS_pDocumentBuf],ax ; and use that one instead
DbAssertRel ax,ne,0,UI,<UiDelAll:NewBuf failed>
DelAllExit:
cEnd
;**************************************************************************
;FreeCmdHistory
;Purpose:
; This is called when we're getting real tight on memory
; and something needs to be done to free up enough to do
; the most primitive operations
;Exit:
; Caller's grs.oRsCur and txtErr are preserved
;
;**************************************************************************
cProc FreeCmdHistory,<PUBLIC,NEAR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -