📄 uinhelp.asm
字号:
TITLE uinhelp.asm - utilities for new help engine.
;***
;uinhelp.asm
;
; Copyright <C> 1985-1988, Microsoft Corporation
;
;Purpose:
; Utilities for the new help system.
;
;
;*******************************************************************************
.xlist
include version.inc
.list
UINHELP_ASM = ON
include cw/version.inc
include cw/windows.inc
include cw/edityp.inc
IncludeOnce architec
IncludeOnce heap
Include help.inc
IncludeOnce parser
IncludeOnce prstab
IncludeOnce rtps
IncludeOnce qbimsgs
IncludeOnce ui
IncludeOnce uiint
IncludeOnce uimenu
IncludeOnce uinhelp
assumes DS,DATA
assumes ES,DATA
assumes SS,DATA
subttl DATA segment definitions.
page
sBegin DATA
externW iMsgStatusLine ; current status line message
externW iHelpId
; GetHelpMessage and MapLineToContext return codes
globalB fHelpAlloc,0 ; Non-zero if help system is doing
; a far heap allocation
BdlTemp BDL <> ; temporary BDL owner
externB bdlHelp ; BDL for keyword help (def in UIHELP.C)
externW szDialogHelpContext ; *sz context of current dialog help
externB b$Buf1 ; FILNAML-sized buffer
externB b$Buf2 ; 16-byte buffer
HtSpot EQU b$Buf2 ; Static HotSpot structure
globalB HelpFlags,0,1 ;status of the help system
globalB HelpFlags2,0,1 ;more help system state
;BUFFERING:
;
; The Help system uses a circular buffer of buffers to hold the
; text of help messages (called contexts) so that scrolling up
; and down in a file does not have to be continuously hitting the
; disk. The buffers are organized as follows:
;
; HelpBuffer : Slot 1 : Slot 2 : Slot 3 : ... : Slot MAX_HELPBUFS :
;
; Each active slot in the Static HelpBuffer is of type HelpBufType. The
; entries in HelpBuffer are organized as a circular list so that they
; may grow on either end without moving the existing entries. Each
; active entry in HelpBuffer represents one context that is currently
; stored in memory.
;
staticW oFirstBuf,,1 ;Offset of first logical buffer
staticW oLastBuf,,1 ;Offset of last logical buffer
staticB numBuf,0,1 ;number of active buffers in HelpBuffer
staticB fNoDelBufs,0,1 ; are we allowed to delete the
; buffers during a ShrinkHelp?
MAX_HELPBUFS = 9 ; Number of entries in HelpBuffer
BUFSIZE = SIZE HelpBufType;The size of the entries in HelpBuffer
BUFFERSIZE = MAX_HELPBUFS * BUFSIZE ; Size of HelpBuffer
staticB HelpBuffer,0,BUFFERSIZE
BUFFEREND EQU (OFFSET DGROUP:HelpBuffer) + (BUFFERSIZE)
DbPub HelpBuffer
globalW iCurRequestLine,UNDEFINED,1 ; line # to get attributes for,
; or UNDEFINED if no attributes
; available
globalW oCurTopic,0,1 ; offset to the current topic
; (0 if no current topic)
globalW iFileSize,0,1 ; Size of current help topic
externW iStaticHelpTopic ; High word of NC during searches
externW WndHelp ; Help Window structure
externW efHelp ; Editmgr structure for Help Wnd.
;QUEUE MANAGEMENT
;
; In order to support help history (Ctrl-F1), we keep a LIFO queue
; of the last 20 items that we requested help on. The items are stored
; as a circular list, with a pointer to the next item to be filled in
; and a count of the number of items that exist.
;
;
; This list (of type HelpHistEntry) is contained in a BDL, with the first
; few bytes of the BDL containg a header (type HelpHistHeader) of useful
; information
;
BdlHelpHist BDL <> ; BDL for help backup (^F1) list
ncInitial DD 0
HelpHistEntry STRUC
HH_HiWord DW ?
HH_LoWord DW ?
HelpHistEntry ENDS
HelpHistHeader STRUC
HH_Used DW ? ; number of history items in use
HH_First DW ? ; offset into seg of next free item
HelpHistHeader ENDS
NUM_HISTORY = 20 ; number of items that can be saved
HELPHIST_BEGIN = Size HelpHistHeader ; offset of first item in segment
HELPHIST_END = HELPHIST_BEGIN + NUM_HISTORY * SIZE HelpHistEntry
; end of the last item
;MAGIC EDIT MANAGER Variables
;
; The following magic locations in the edit manager are used:
;
; EfHelp.EF_ipCur_ob = Current column in help window
; EfHelp.EF_ipCur_oln = Current line in help window
; EfHelp.EF_pdCur_olnTop = Top line of help window
; EfHelp.EF_pdCur_obleft = Leftmost column of help window
;
; WndHelp.arcClipping.ayBottomArc, WndHelp.arcClipping.ayTopArc
; specify the top and bottom of the window. I believe
; that they are in screen coordinates.
;
; One thing to note: The Edit Manager uses 0 relative coordinates
; while the helpengine (and variable help) use 1 relative coordinates.
; Thus, you have to be careful in converting from one to another.
;
; There are only 2 places that a line or column number is stored:
; - Bookmarks (0 relative, as the HelpEngine is not involved)
; - iCurRequestLine (1 relative, because it is a HelpEngine line#)
;
;HELP System ENTRY/EXIT conditions
;
; Anytime that code for the help system is executing, we must have the
; following conditions met:
;
; 1.) As close as possible to the point where we could display a
; dialog box or message box receiveing ANY input from the user
; we must have HLP_INHELP set to prevent recursively entering the
; help system. Currently, this occurs in 2 places:
; - Displaying "Help File Not Found"
; - Displaying "INsufficient memory for help system"
;
; 2.) The help system must be active to the level that is needed to
; implement the desired functionality. There are three levels:
;
; a.) Help Engine shut down - No functionality at all possible.
;
; b.) Help Engine Active, no current topic.
; HLP_GOTBUF is true, but oCurTopic = 0.
;
; c.) Help Engine Active, Current topic available.
;
;
; The following assumptions and conditions are used in checking
; entry conditions:
;
; - If the help window is open, we must be at level C.
; - If the help window is closed, we may be at A or B.
; - If we get a message from the help window, it must be open (C).
; - If StartHelp returns 0, you are in either B or C.
;
; 3.) Any allocation could end up causing CompressHelp to be called.
; Thus, there has to be flag set ANYTIME we are in the help system
; so that CompressHelp will not yank the help system out from
; underneeth itself. Currenly, there are only 2 entry points
; for help:
; - Help()
; - HelpWndProc()
sEnd DATA
externFP B$IFOUT ; Convert number to string
externFP HelpOpen ; Misc Help engine routines
externFP HelpNc
externFP HelpNcCb
externFP HelpLook
externFP HelpDecomp
externFP HelpXRef
externFP HelpGetLine
externFP HelpHlNext
externFP HelpNcNext
externFP HelpSzContext
externFP HelpClose
externFP HelpShrink
externFP _atoi ; CONSIDE: use runtime call for this
externFP fEditorActive
externFP fQhelpActive
sBegin UI
assumes CS,UI
staticB szHelpFileEdit,<"EDIT.HLP",0> ; main help file name
staticB szHelpFileQhelp,<"HELP.HLP",0> ; qhelp help file name
staticB szHelpFileInterp,<"QBASIC.HLP",0> ; second help file name
externNP MoveCursorPwndCur ; Move cursor of current window
externNP MoveCursorPwnd ; Move cursor of specified window
externNP WndHelpOpen ; Open help window to a given size
externNP WndHelpClose ; Close the help window
externNP SetHelpKeyword ; put keyword into help syntax menu
externNP HelpBack
subttl Main Help EntryPoints
page
;***
;KeywordHelp : Display help for a keyword
;
;Purpose:
; This routine implements SHIFT-F1. If the cursor is on a keyword
; in a window, then display help for this keyword in the help window
; (opening it if needed). If there is no text selected, or it is
; not a keyword, then return a non-zero value to indicate that F1
; should be done.
;
;Entry:
; None.
;
;Exit:
; None
;
;Uses:
; AX,BX,CX,DX
;
;****
cProc KeywordHelp,<NEAR,PUBLIC>,<SI>
cBegin
cCall StartHelp ; make sure we have the help system
or ax,ax ; did we succeed?
jne KeywordHelpExit ; no, just return
cCall KeywordHelpLookup ; AX = length of current keyword
; (text placed in bufStdMsg)
or ax,ax ; is there a current keyword?
jne CurKeyword ; brif so
Moo:
cCall CowMoo ; -- beep speaker & return
jmp short KeywordHelpExit
CurKeyword:
DbChk HoldBuf1 ; grab B$Buf1
mov ax,offset dgroup:bufStdMsg ; where the topic was placed
mov bx,offset dgroup:B$Buf1 ; new home for the topic string
push bx ; param to DisplayHlpWndSz
cCall fstrcpy2,<DS,bx,DS,ax>
cCall DisplayHlpWndSz ; try to display the help
DbChk FreeBuf1 ; release the buffer
or al,al ; Did we succeed with engine hlp
je KeywordHelpExit_Ok ; yes, exit.
test al,HELP_HANDLED ; have we displayed anything to
; the user?
jnz KeywordHelpExit ; yes, just exit
jmp short Moo ; otherwise tell user about it
KeywordHelpExit_Ok:
mov [uierr],0 ; clear any leftover errors
KeywordHelpExit:
cEnd
;***
;KeywordHelpLookup : Find help for a keyword
;
;Purpose:
; Added with revision [5].
;
; Looks up the keyword, enables/disables the HelpSyntax menu item, and
; puts the keyword into the HelpSyntax menu item.
;
;Entry:
; None.
;
;Exit:
; AX : =0 if no keyword was found
; length of keyword (NZ) if keyword was found
;Uses:
; AX,BX,CX,DX
;
;****
cProc KeywordHelpLookup,<NEAR,PUBLIC>
cBegin
mov ax,offset dgroup:bufStdMsg
mov bx,10 ; maximum length of word (10 is magic)
mov cx,GEW_HELPMASK ; do not include . or ! in search
cCall GetEditWordMask,<ax,bx,cx> ; AX = length of word retrieved
push ax ; save for return value
; enable/disable help syntax menu item based on AX (0 ==> disable)
or ax,ax ; if NZ, set low bit for stupid-ass
jz disableit ; COW C function
mov al,1
disableit:
mov bx,midHelpSyntax
cCall EnableMenuItem,<bx,ax>
; copy current topic name into help syntax menu buffer
mov ax,offset dgroup:bufStdMsg
cCall SetHelpKeyword,<ax>
pop ax ; return AX = length of keyword
cEnd
;***
;SelectHotLink - Go to the hot link that is specified in the window coords
;
;Purpose:
; Look in the help file given by the line number and column
; number. If there is a hot link at this position, go to the item
; that it links to. Otherwise, just returns.
;
;Entry:
; (rx,ry) - virtual line coordinates of the location of a
; supposive hot spot.
; beep - TRUE if we are suspose to beep when we don't find anything
;
;Exit:
; AX = 0 (FALSE) if a hot link was selected
;
;Uses:
; Per Convention
;****
cProc SelectHotLink,<PUBLIC,NEAR>,<SI,DI>
parmW rx
parmW ry
parmB GiveBeep
cBegin
;Since we got a keyboard message from the help window, it must be
;open, therefor we must be initialized.
DbAssertTst HelpFlags,ne,HLP_GOTBUF,UI,<SelectHotLink:Buffers Not Initialized>
DbChk HoldBuf2 ; lock down the HotSpot
DbChk HoldBuf1 ; for composed hotlink names
mov bx,oCurTopic ; get ptr to topic
lea bx,[bx].bdlHelpText.BDL_seg ; BX = handle to data seg
mov cx,rx
inc cx ; make column 1 relative
mov HtSpot.colHS,cx
mov cx,ry ; get line number
inc cx ; make it 1 relative
mov HtSpot.lineHS,cx ; and stick in HotSpot structure
mov ax,OFFSET DGROUP:HtSpot
xor cx,cx
and HelpFlags,NOT (HLP_FAILFNF OR HLP_FAILOOM) ; clear errors
cCall HelpXRef,<BX,CX,DS,AX> ;Get context string for topic
or ax,ax ; did we get a topic
jnz GotSelection ; yes, go display it
test HelpFlags,HLP_FAILFNF OR HLP_FAILOOM ; is error handled?
jnz NoBeep ; yes, do not beep
SelectHotLink_Beep:
cmp GiveBeep,0 ; should we give a beep?
je NoBeep ; no, just exit with error code
cCall CowMoo ; beep cow's speaker
NoBeep:
mov ax,sp ; return with non-zero value
DbChk FreeBuf2 ; release the HotSpot
DbChk FreeBuf1 ; and our other buffer
jmp short NoSelection ; and exit
GotSelection:
;Copy context string into free part of Buf2 and display it in a help
;window. The source string is in HtSpot.pXrefHS and is 0 terminated
;We can not use the source directly, as it points into a BDL, and
;we are not guarenteing a locked heap.
push ds ; set ES = DS = DGROUP
pop es
mov di,offset dgroup:b$buf1 ; ES:DI = destination
push di ; parm for DislplayHlpWnd
lds si,DWord Ptr HtSpot.pXrefHS ; DS:SI = source
CopyLoop:
lodsb ; copy the byte
stosb
or al,al ; is it the 0 termiantor
jne CopyLoop ; no, do next byte
lodsw ; Copy next word
stosw ; incase it was local
push es ; restore DGROUP
pop ds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -