📄 uiedit.asm
字号:
TITLE uiedit.asm - Misc user interface functions.
;***
;uiedit.asm
;
; Copyright <C> 1985-1988, Microsoft Corporation
;
;Purpose:
; Interface between CW and parsing code.
;
;
;*******************************************************************************
.xlist
include version.inc
UIEDIT_ASM = ON
CONTEXT_NOFUNCS = ON
include cw/version.inc
include cw/windows.inc
include cw/edityp.inc
IncludeOnce architec
IncludeOnce context
IncludeOnce lister
IncludeOnce heap
IncludeOnce parser
IncludeOnce pcode
IncludeOnce qbimsgs
IncludeOnce rtps
IncludeOnce txtmgr
IncludeOnce ui
IncludeOnce uiint
IncludeOnce uinhelp
IncludeOnce util
IncludeOnce edit
.list
assumes DS,DATA
assumes SS,DATA
assumes ES,NOTHING
;-------------------------------------------------------------------------
; DATA Segment Declarations
;-------------------------------------------------------------------------
sBegin DATA
; oRs of 'command window'
globalW hbufOfCmd,UNDEFINED
; oRs of 'scrap' used as temporary buffer
; for Cut/Copy/Paste operations
globalW hbufOfScrap,UNDEFINED
; since we list one line after another when refreshing the content
; of a window, these static variables are used to remember where the
; pcode offset for the next line to be listed. It saves us from
; having to search pcode for the nth line. It must be discarded
; whenever text changes, or another text table is activated.
staticW otxLnLast,0
staticW otxGetNext,0
staticW lnGetNext,0
staticW saveLnGetNext,0
staticW saveOtxGetNext,0
staticW saveRsCur,UNDEFINED
; The number of the last line entered in the command windows is kept here.
; For error reporting.
staticW lnCmdLast,0
; Set to TRUE when a command in the parse buffer should be executed.
globalW fDoCmd,0
; Set to TRUE when we have an error that may need the box to be repositioned
; depending upon where the cursor position is (see uimsgbox.c)
globalB fAdjustMsgBox,0
;cbGetLineBuf sets the following two words for LineAttr
staticW colStmtStart,0
staticW colStmtEnd,0
staticB fWndHelp,0
; rgLineAttr is used in GetLineAttrs
public rgLineAttr
rgLineAttr label word
rgLineAttr0 db size LINEATTR dup(?)
rgLineAttr1 db size LINEATTR dup(?)
rgLineAttr2 db size LINEATTR dup(?)
rgLineAttr3 db size LINEATTR dup(?)
;BOOKMARKS:
; Each bookmark is specified in the following structure. Different
; fields are UNDEFINED (-1) to indicate different conditions or
; situation with the bookmark
;
; if BM_oRs == UNDEFINED
; bookmark is invalid
;
; if BM_Nc == NOT_HELPTOPIC
; BM_oRs = register set for non-help window
; BM_oln = line number in the window
; BM_col = column number in the window
; else if BM_oln == UNDEFINED && FV_VARHELP
; BM_oRs = register set of variable help item
; BM_Nc = oName of variable help item
; BM_col = column number in the window
; else
; BM_Nc:BM_oRs = context number of help item
; BM_oln = line number in the window
; BM_col = column number in the window
;
;NOTE: it is Nc:oRs for help engine help but oRs:Nc for Variable help
; (so that we can deallocate based on the oRs).
BookMark struc
BM_Nc dw UNDEFINED ; oRs for non-help window. Otherwise,
BM_oRs dw UNDEFINED
BM_oln dw 0
BM_col dw 0
BookMark ends
.errnz (-1) - (UNDEFINED)
NOT_HELPTOPIC equ UNDEFINED
MAXBOOKMARK equ 4
BookMarks BookMark MAXBOOKMARK dup(<>)
psSaveLen dw 0
psSaveChar db 0
;
; ldEMScratch is used by TWIN's EditMgr.
; Since we want is to be a movable heap entry, the structure overlaps a bd.
;
public ldEMScratch
public bdEMScratch
.errnz (size ld) - 8
.errnz (size bd) - 6
ldEMScratch dw 0 ; ld.flags ---+
dw 0 ; ld.cb |--------- ld structure
bdEMScratch dw 0 ; ld.cbMax/bd.cbLogical | ----+
dw 0 ; ld.prgch/bd.pb ---+ |--- bd Structure
dw 0 ; bd.cbPhysical ---------+
;next 4 locations are used to construct special dialog for
;runtime errors in compiled code (in ReportError()).
EXTRN b$fCompErr:word ;non-zero if error was in compiled code
EXTRN b$ErrLin:word ;line # of last runtime error (ERL)
EXTRN b$ErrMod:dword ;far ptr to 0-terminated module name
EXTRN b$ErrAdr:dword ;far ptr where runtime call was made
EXTRN b$ErrInfo:byte ;extended error code
EXTRN iHelpId:word
externB HelpFlags
sEnd DATA
sBegin UI
assumes CS,UI
externNP WndHelpOpen ; Open help window to a given size
externNP DisplayHelpOOM
;Extended out-of-memory error messages.
; Moved FAR to save DGROUP
twExtOmErr LABEL WORD
dw ER_OM ;"Out of memory"
dw MSG_OutNearMem ;"Out of data space"
dw ER_OM ;"Out of memory"
dw MSG_OutOfStack ;"Out of stack space"
dw MSG_ProcTooLarge ;"Procedure too large"
dw MSG_ModTooLarge ;"Module level code too large"
dw MSG_InclTooLarge ;"Include file too large"
dw MSG_DocTooLarge ;"Document too large"
.errnz OMErr_OM -0 ;generic OM error
.errnz OMErr_NH -1 ;out of near heap space ( DS > 64k )
.errnz OMErr_FH -2 ;out or far heap space ( out of system memory )
.errnz OMErr_STK -3 ;out of stack space
.errnz OMErr_Proc-4 ;out of Procedure text table space ( > 64k )
.errnz OMErr_Mod -5 ;out of Module text table space ( > 64k )
.errnz OMErr_Inc -6 ;out of Include file text table space ( > 64k )
.errnz OMErr_Doc -7 ;out of Document file text table space ( > 64k )
;**************************************************************************
; EditMgrFlush
; Purpose:
; Flush the current line out of the editor's internal buffer if
; it is dirty.
; Since replacing the line could cause a procedure to be renamed
; which gives it a different oRs, this routine does not preserve
; grs.oRsCur (and the caller shouldn't either). The reason
; the oRs of the procedure needs to change is because there
; may be references to the old prs in pcode, so the old prs has
; to stay.
; EditMgrFlush1 has same entry conditions and purpose, only it
; flushes the edit mgr's buffer even if edit mgr's buffer isn't dirty.
; This is used when:
; [1] window allocation changes on the screen, so the edit mgr
; forces the cursor within the current window.
; [2] when QB is going to use the edit mgr's buffer for its own
; purposes, so it doesn't want subsequent edit mgr calls
; to think what it has cached in this buffer represents its
; current line.
; Exit:
; ReplaceLineBuf will be called if line was dirty, which can
; modify ps.bdpSrc among other things...
; Active window's oRs is active.
;
;**************************************************************************
PUBLIC EditMgrFlush, EditMgrFlush1
EditMgrFlush1 PROC NEAR
sub cx,cx
SKIP2_PSW
EditMgrFlush1 ENDP
EditMgrFlush PROC NEAR
mov cl,1
DbAssertRel [pwndAct],ne,0,UI,<EditMgrFlush: pwndAct=NULL>
; brif we're to do it even if no dirty buffer (it causes editmgr
; to force the cursor within the current window).
jcxz EfFlushFocus
;While edit mgr is active, it has local copy of ldFlags.
DbAssertTst [emFlags],e,EMF_IN_EDITMGR,UI,<EditMgrFlush: EditMgr active>
mov bx,[pwndAct]
mov bx,[bx.pefExtra]
mov bx,[bx.EF_pldCur]
test [bx.LD_flags],LD_fDirty ;test fDirty flag in window's structure
je EfExit ;brif not dirty (speed optimization)
EfFlushFocus:
cCall FlushFocus
SkipFocus:
cCall UiRsActivateWnd ;activate active window's oRs
EfExit:
ret
EditMgrFlush ENDP
cProc FlushFocus,<NEAR>,<si>
cBegin
mov si,[pwndAct]
mov bx,WM_FLUSHFOCUS ; New EditMgr message
sub cx,cx
cCall SendMessage,<si,bx,cx,cx,cx>
cEnd
;**************************************************************************
; void FAR UiFlushCache()
; Purpose:
; Called by text manager whenever text is changed, or cached text offsets
; become invalid for any other reason.
; Also called every time a context change occurs.
; It resets any variables which speed performance by assuming we're
; in the same context we were the last time the variables were set.
; We flush our cache so we don't look at invalid data.
;
; Entry:
; none
;
; Exit:
; lnGetNext = 0
;
;**************************************************************************
cProc UiFlushCache,<PUBLIC,FAR>
cBegin
mov [lnGetNext],0 ;Clear cache
cEnd
;**************************************************************************
; void KludgePs()
; Purpose:
; Null terminates ps.bdpSrc.pb and saves info to restore it
; later via UnKludgePs.
;
; Entry:
; [ps.bdpSrc.pb]
; cx - length of string at ps.bdpSrc.pb
; Exit:
; [psSaveLen]
; [psSaveChar]
;
;**************************************************************************
cProc KludgePs,<NEAR>
cBegin
mov bx,[ps.PS_bdpSrc.BDP_pb]
add bx,cx
xor al,al
xchg al,[bx]
mov [psSaveChar],al
mov [psSaveLen],cx
cEnd
;**************************************************************************
; void UnKludgePs()
; Purpose:
; Reverses effects of KludgePs.
;
; Entry:
; [ps.bdpSrc.pb]
; [psSaveLen]
; [psSaveChar]
; Exit:
; ps.bdpSrc.pb is restored to state before KludgePs
;
;**************************************************************************
cProc UnKludgePs,<NEAR>
cBegin
mov bx,[ps.PS_bdpSrc.BDP_pb]
add bx,[psSaveLen]
mov al,[psSaveChar]
mov [bx],al
cEnd
;**************************************************************************
; void near UpdAltListWnd(ax=lnTop, dx=delta)
; Purpose:
; Update the alternate-list-window if 2 list windows are active
; and both refering to the same text table.
; Entry:
; ax=lnTop is the top line affected by the edit
; dx=delta is the number of lines inserted or deleted
; For example: inserting 1 line after line 0: lnTop=0, delta=1
; deleting 1 line after line 0: lnTop=0, delta=-1
; replacing line 5: lnTop=5, delta=0
;
;**************************************************************************
DbPub UpdAltListWnd
cProc UpdAltListWnd,<NEAR>
cBegin
cmp [fWndSplit], 0
je UAltExit
mov bx, DATAOffset wnd1
cmp bx, [pwndAct]
jne @f
mov bx, DATAOffset wnd2
@@:
mov bx,[bx.pefExtra]
mov cx,[grs.GRS_oRsCur]
cmp cx,[bx.EF_hBuffer]
jne UAltExit ;brif both don't refer to same txt tbl
or dx,dx
jns NotDel ;brif lines are not being deleted
mov cx,ax ;cx = lnTop
sub cx,dx ;cx = 1st line above deleted lines
cmp cx,[bx.EF_pdCur.pd_olntop]
jbe NotDel ;brif entire delete is below window top
mov dx,ax ;cx = lnTop
sub dx,[bx.EF_pdCur.pd_olntop]
;dx = -#lines deleted below window top
NotDel:
cmp ax,[bx.EF_pdCur.pd_olntop]
jae UAltNoChg ;brif top line is unaffected by edit
add [bx.EF_pdCur.pd_olntop],dx
UAltNoChg:
call DrawDebugScr ;sledge hammer ok for uncommon state
UAltExit:
cEnd
;**************************************************************************
; void near ActivateHbuf
; Purpose:
; Tell the context manager to make the module/procedure associated with
; the list window identified by hbuf active.
;
; Algorithm:
; If hbuf is not already active
; if hbuf is for scrap
; saved = current
; else if hbuf <> saved
; saved = undefined
; Activate hbuf
; if hbuf = saved
; current = saved
; saved = undefined
; Entry:
; BX = hbuf - is the handle for a text table.
; It is really an oRs (see context.h) for the text table .
;
; Exit:
; The text table associated with hbuf is activated.
;
;**************************************************************************
cProc ActivateHbuf,<NEAR>
cBegin
DbAssertRel bx,ne,UNDEFINED,UI,<ActivateHbuf(UNDEFINED)>
mov [grs.GRS_fDirect],FALSE
cmp bx,[grs.GRS_oRsCur]
je AHB_End ;brif hbuf is already active
;This optimization is important,
;because UiRsActivate calls UiFlushCache
;which zeros lnGetNext, which is used
;to speed up cbGetLine.
;Now we do a speed optimization for CUT and COPY so cbGetLineBuf
;can be fast even though we are swapping a user's and scrap's text
;tables on a per-line basis.
cmp bx,[hbufOfScrap]
jne NotScrap1 ;brif not activating the scrap
mov ax,[lnGetNext] ;save cached variables used to
mov [saveLnGetNext],ax ; make cbGetLineBuf fast
mov ax,[otxGetNext]
mov [saveOtxGetNext],ax
mov ax,[grs.GRS_oRsCur]
mov [saveRsCur],ax
jmp SHORT NotScrap2
NotScrap1:
cmp bx,[saveRsCur]
je NotScrap2 ;brif activating rs other than scrap
mov [saveRsCur],UNDEFINED ; or saveRsCur - end of Cut/Copy/Paste
NotScrap2:
cCall UiRsActivate,<bx>
mov ax,[grs.GRS_oRsCur]
cmp ax,[saveRsCur]
jne NotScrap3 ;brif not activating rs which was active
; before scrap was last activated.
mov ax,[saveLnGetNext] ;restore cached variables that make
mov [lnGetNext],ax ; cbGetLineBuf fast
mov ax,[saveOtxGetNext]
mov [otxGetNext],ax
mov [saveRsCur],UNDEFINED
NotScrap3:
AHB_End:
cEnd
;**************************************************************************
; ModifyingHbuf
; Purpose:
; Same as ActivateHbuf but also does TxtModified
;
; Entry:
; BX = hbuf - is the handle for a list window (an oRs).
;
; Exit:
; The text table associated with hbuf is activated and descanned.
;
;**************************************************************************
ModifyAndGrab PROC NEAR
cmp bx,[hbufOfCmd]
je ModifyingHbuf ;brif edit is in Command Window
; user should be able to type
; CLEAR even if he's low on memory
push bx
call UiGrabSpace ;don't let user enter such a long
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -