📄 uimain.asm
字号:
; to discard module(s).
; If any module has been modified since last saved, a dialog box asks
; the user if the module(s) are to be saved.
; If user selects Yes,
; CmdFileSaveAll is invoked
; If any errors occur during CmdFileSaveAll, an error code is returned.
; else the function returns 0.
; If user selects Cancel,
; it returns MSG_GoDirect, which is not trappable,
; and eventually gets us back into user interface, which does not
; report this special MSG_GoDirect runtime error.
; If user selects No,
; the function returns -2.
; Else if no modules need to be saved,
; it just returns -1.
;
; NotSavedInc just does this for INCLUDE mrs's with the prompt:
; "Modified $INCLUDE files must be saved before running. Save them now?"
;
; NotSavedIncSav just does this for INCLUDE mrs's with the prompt:
; "Save modified $INCLUDE files first?"
;
; Entry:
; none
;
; Exit:
; returns 0 if all modified files were saved without error,
; returns -1 if no files were modified (and thus not saved)
; returns -2 if user responded NO to the prompt
; returns MSG_GoDirect if user responded CANCEL to the prompt
; returns error code in ax if an I/O error occurred while trying to save.
;
;*********************************************************************
PUBLIC NotSaved, NotSavedInc, NotSavedIncSav
NotSavedIncSav PROC FAR
mov al,2
SKIP2_PSW ;skip following mov al,1 instruction
NotSavedIncSav ENDP
NotSavedInc PROC FAR
mov al,1
SKIP2_PSW ;skip following mov al,0 instruction
NotSavedInc ENDP
NotSaved PROC FAR
mov al,0
;Common entry for NotSaved, NotSavedInc
push si ;save caller's si,di
push di
cbw ;ax = fInclude
xchg di,ax ;di = fInclude
mov [uierr],0 ;need to init uierr, because it
; could be non-zero if user selected
; File/Exit with dirty line in editor.
call EnStaticStructs ;activate static prsCur, mrsCur, txdCur
;cx = 0 if no action taken
push ax ;remember if we need to call DisStatic..
push WORD PTR([grs.GRS_fDirect])
push [grs.GRS_oRsCur] ;save caller's oRs (for UiRsActivate)
mov si,UNDEFINED
.erre IDCANCEL - UNDEFINED ; (it will be tested below)
.erre IDNO - UNDEFINED ; (it will be tested below)
.erre IDYES - UNDEFINED ; (it will be tested below)
;pass UNDEFINED to UiRsActivate so no mrs is active
cCall UiRsActivate,<si>
NsLoop:
call NextMrsFile_All ; activate next mrs that has a FILE
; NextMrsFile doesn't pick up an
; empty <Untitled> module.
inc ax ;test for UNDEFINED
je NsDone ;brif done with all mrs's
test [mrsCur.MRS_flags2],FM2_Modified
je NsLoop ;brif module is unchanged
or di,di
je SaveIt ;brif saving ALL files, not just INCLUDE
test [mrsCur.MRS_flags2],FM2_Include
je NsLoop ;brif this isn't an INCLUDE file
SaveIt: ;Got at least 1 module which needs to be saved - ask user
PUSHI ax,MB_YESNOCANCEL
mov ax,MSG_NotSavedAll
.errnz MSG_NotSavedInc - MSG_NotSavedAll - 1
.errnz MSG_NotSavedIncSav - MSG_NotSavedAll - 2
add ax,di ;bump to MSG_NotSavedInc if fInclude
push ax
call MsgBoxStd ;al = reply
cmp al,IDYES
xchg si,ax ;save user's response in si
jne NsNoSave ;brif NO or CANCEL reply
xor ax,ax ; no title for subsequent dialog
xchg ax,szDialogTitle ; boxes (save all)
push ax ; save current dialog box title title
cCall CmdFileSaveAll,<di> ;save all modified modules
pop szDialogTitle ; restore current dialog box title
or ax,ax
jne NsNoSave ;brif user didn't select CANCEL in
; Save dialog, and no I/O errors
mov si,IDCANCEL
NsNoSave:
;At this point, si = UNDEFINED if no files needed to be saved,
; IDNO if user chose to not save unsaved files,
; IDCANCEL if user wants to back out of current operation,
; IDYES if all files were saved,
; (uierr = non-zero if any errors occurred while saving)
;
NsDone:
call UiRsActivate ;activate stacked register set.
pop ax ;ax = saved value of grs.fDirect
mov [grs.GRS_fDirect],al ;restore it
pop cx ;cx=0 if static structs were already
jcxz NsStatic ; enabled when NotSaved was called
call DisStaticStructs ;ensure static structs deactivated
NsStatic:
;If CANCEL button was pressed, return untrappable runtime error
;which will get us back into user interface if we were in the
;middle of CHAIN/RUN <file>
mov ax,[uierr]
or ax,ax
jne NsExit ;brif I/O error during save
mov al,MSG_GoDirect
cmp si,IDCANCEL
je NsExit ;brif user responded CANCEL
sub ax,ax ;ax = 0
cmp si,IDYES
je NsExit ;return 0 if any/all files saved
dec ax ;ax = -1
inc si ;test for UNDEFINED
je NsExit ;return -1 if no files need to be saved
dec ax ;if user said NO, return -2
NsExit:
pop di ;restore caller's si,di
pop si
or ax,ax ;set condition codes for caller
ret
NotSaved ENDP
;**************************************************************************
; UiGrabSpace
; Purpose:
; Don't let user enter such a long program that he can't even execute
; a SYSTEM, CLEAR, or SETMEM statement.
; VERY IMPORTANT: Every call to UiGrabSpace MUST be balanced by
; a subsequent call to UiReleaseSpace. Make sure the code in
; between can't take pathological branches (RtError) or non-pathological
; branches around the UiReleaseSpace call.
;
; The goal of user-interface tight-memory-management is to never
; let the user get so low on memory that they get locked up
; (i.e. so tight they can't even delete some text or unload a module
; or execute a direct-mode clear/setmem statement). If they
; get locked up to the point where they can't save their file,
; it is as bad as crashing.
; Part of the strategy involves reserving memory whenever the
; user could potentially be making long-term memory commitments
; (i.e. loading a new module or inserting a new line of text)
; Another part of it is having UiGrabSpace release any
; "discretionary memory" it can when we run out of memory.
;
;**************************************************************************
cProc UiGrabSpace,<PUBLIC,NEAR>
cBegin
inc [cGrab]
call GrabSpace
or ax,ax
jne GotSpace ;brif got space
;We're very low on memory
;Release any discretionary info we can to give us the space we need.
call AlphaORsFree ;release sorted alphabetised list
; of modules/procedures - we build
; it whenever we need it.
extrn FreeCmdHistory:near
call FreeCmdHistory ;release command window's history
call GrabSpace ;should never fail.
GotSpace:
cEnd
;**************************************************************************
; UiReleaseSpace
; Purpose:
; We're not in an area where we could make long-term memory commitments
; that would prevent us from doing a SYSTEM, CLEAR, or SETMEM statement.
; Unlike ReleaseSpace(), this function doesn't release the space
; unless all nested callers of UiGrabSpace have released their hold.
;
;**************************************************************************
cProc UiReleaseSpace,<PUBLIC,NEAR>
cBegin
DbAssertRelB [cGrab],ne,0,UI,<UiReleaseSpace: cGrab=0>
dec [cGrab]
jne NotDone ;brif not everyone that called
call ReleaseSpace ; UiGrabSpace has called UiReleaseSpace
NotDone:
cEnd
;**************************************************************************
; UiAlphaORsBuild
; Purpose:
; Since AlphaORsBuild allocates a heap entry, we need to make sure
; it doesn't encroach upon the minimum heap the user interface needs.
; Exit:
; ax = 0 if out-of-memory
;
;**************************************************************************
cProc UiAlphaORsBuild,<PUBLIC,NEAR>
cBegin
call AlphaBuildORs
cEnd
;**************************************************************************
;**************************************************************************
;EnMenuCall
;Purpose:
; Makes a far call to EnableMenuItem.
;Entry:
; AL = Menu Item Name
; DI = Enable / Disable item
;Exit:
; None
;Usage:
; Saves AX,BX,CX,DX.
;**************************************************************************
cProc EnMenuCall,<NEAR>,<AX,BX,CX,DX>
cBegin
xor ah,ah ; AX = MenuItemName
cCall EnableMenuItem,<ax,di>
cEnd
;*************************************************************************
;ChMenuCall
;Purpose:
; Makes a far call to CheckMenuItem
;Entry:
; AL = Menu Item Name
; DI = Enable / Disable item
;Exit:
; None
;Usage:
; Per Convention
;*************************************************************************
cProc ChMenuCall,<NEAR>
cBegin
xor ah,ah ; AX = MenuItemName
cCall CheckMenuItem,<ax,di>
cEnd
;**************************************************************************
; MenuEnable - rewritten in assembler from c code in uictl.c
; Purpose:
; Enables Display in Main Window.
; Entry:
; None
; Exit:
; None
; Uses:
; PerConvention
;
;**************************************************************************
cProc MenuEnable,<PUBLIC,FAR>,<DI,SI>
cBegin
cCall UiRsActivateWnd ; Tell context manager to activate
; active window's register set
; The Edit Field Structure is updated by every cursor movement
; indicating system's current state, in terms of options available.
; For example at the begining of qb sesbx on with blank screen, i.e.
; no files loaded, you would not have any 'Edit' options available.
; the moment you type anything 'Undo' becomes available. Further
; until you select and 'cut', 'paste' would not be availble.
mov bx,pwndAct ; bx = pointer to active window's reg set
mov bx,[bx.pefExtra] ; bx = * to edit field structure
push bx ; Save for later use
mov bl,[bx.EF_fSelection]
xor bh,bh ; BX = fSelection from edit field structure
xor cx,cx ; if pwndAct != wndCmd then ListWnd=False
cmp pwndAct,DATAOFFSET wndCmd; else ListWnd=True
je fIsListWndSet ; CX = ListWnd Status
dec cx
fIsListWndSet:
xor dx,dx ; So no changes like cut, paste
cmp pwndAct,DATAOFFSET wndHelp ; are allowed. fChangeable flag
je fChangeableSet ; specifies if user is in Help.
dec dx
fChangeableSet: ; DX = fChangeable
mov si,dx ;SI = fChangeable
mov di,bx ; DI = fSelection
mov al,midEditCopy ; Set up Edit/Copy
cCall EnMenuCall
and di,si ; DI = fSelection AND fChangeable
mov al,midEditCut ; Setup Edit/Cut
call EnMenuCall
mov al,midEditClear ; Set up Edit/Clear
cCall EnMenuCall
mov al,fPasteOk
cbw
xchg di,ax ; DI = Paste Command availability status
and di,si ; DI = fPasteOK AND fChangeable
mov al,midEditPaste ; Set up Edit/Paste
cCall EnMenuCall
mov di,cx ; DI = ListWindow Status
mov al,midSearchFind ; Set up Search/Find
cCall EnMenuCall
mov al,midSearchNext ; Set up Search/Next
cCall EnMenuCall
and di,si ; DI = ListWnd AND fChangeable
mov al,midSearchChange ; Set up Search/Change
cCall EnMenuCall
; bx was save way above.
pop bx ; Restore bx = * Edit Field Structure
mov al,fSyntaxCheck
cbw ; AX = Syntax Check options Selected?
xchg di,ax ; DI = Syntax Check options
mov al,midOptnsSyntax ; in Options of menus
cCall ChMenuCall
xor cx,cx
xor ah,ah
mov al,[mrsCur].MRS_flags2 ;get mrs file flags
and al,FM2_Include+FM2_NoPcode ;is this a pcoded window?
jnz SetFalse ; brif not
dec cx
SetFalse:
mov dx,si ; DX = fChangable
and dx,cx ; fIsCodeWnd = Pcode & Changeable
; DX = fIsCodeWnd, CX = fPcode
mov di,dx ; DI = IsCodeWnd
mov al,midEditNewSub ; Setup Edit/New Sub
cCall EnMenuCall
mov al,midEditNewFunc ; Setup Edit/New Function
cCall EnMenuCall
mov al,midDebugToggleBp ; Set up Debug/Toggle BreakPoint
cCall EnMenuCall
mov al,midGoUntilCursor
cCall EnMenuCall
mov di,fIsProgram ; DI = TRUE if prog, FALSE if doc
mov al,midViewSubs ; Setup View/Subs
cCall EnMenuCall
mov al,midRunStart ; Setup Run/Start
cCall EnMenuCall
mov al,midRunRestart ; Setup Run/Retart
cCall EnMenuCall
mov al,midRunContinue ; Setup Run/Continue
cCall EnMenuCall
mov al,midStep ; Setup Debug/Step
cCall EnMenuCall
mov al,midPStep ; Setup Debug/PStep
cCall EnMenuCall
mov al,midDebugClearAllBp ; Setup Debug/Clear all Bp
cCall EnMenuCall
mov al,midDebugTraceOn ; Setup Debug/Trace On
cCall EnMenuCall
mov di,dx ; di = fIsCodeWnd
or di,di ; is this a code window?
je NotCodeWnd ; brif not
cCall fCanContUI ; returns AX = Execution State
xchg ax,di ; False if Not in Code Window
NotCodeWnd:
mov al,midDebugSetNextStmt; Set up Set Next Stmt command
cCall EnMenuCall ; in debug options of menus
mov al,fTraceOn
cbw
xchg di,ax ; di = Trace On Flag
mov al,midDebugTraceOn ; Setup Debug/Trace On
cCall ChMenuCall
cEnd
sEnd UI
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -