home *** CD-ROM | disk | FTP | other *** search
- ; File......: TMENU.ASM
- ; Author....: Ted Means
- ; Date......: $Date: 15 Aug 1991 23:07:14 $
- ; Revision..: $Revision: 1.2 $
- ; Log file..: $Logfile: E:/nanfor/src/tmenu.asv $
- ;
- ; This is an original work by Ted Means and is placed in the
- ; public domain.
- ;
- ; Modification history:
- ; ---------------------
- ;
- ; $Log: E:/nanfor/src/tmenu.asv $
- ;
- ; Rev 1.2 15 Aug 1991 23:07:14 GLENN
- ; Forest Belt proofread/edited/cleaned up doc
- ;
- ; Rev 1.1 14 Jun 1991 19:55:00 GLENN
- ; Minor edit to file header
- ;
- ; Rev 1.0 01 Apr 1991 01:03:56 GLENN
- ; Nanforum Toolkit
- ;
-
- ; This source code is used by Toolkit sources ATPROMPT.PRG and
- ; MENUTO.PRG. Look at that code for details on the TMENU system.
-
- ; This code depends on "TMENU.INC"
- ;
-
- IDEAL
-
- Public __ftprompt, __ftmenuto
-
- Include "TMENU.INC"
-
- Extrn __ParInfa:Far
- Extrn __ParCLen:Far
- Extrn __ParC:Far
- Extrn __ParNI:Far
- Extrn __RetNL:Far
- Extrn __Ret:Far
- Extrn __XGrab:Far
- Extrn __XFree:Far
- Extrn __XUnlock:Far
-
- Segment _MenuData Word "DATA"
-
- PrCount DW 0
-
- Label HeadPtr DWord ; Pointer to head of linked list
- HeadOfs DW 0 ; of menu items
- HeadSeg DW 0
-
- Ends _MenuData
-
-
- Segment _NanFor Word "CODE"
- Assume CS:_NanFor,ES:_MenuData
-
- Proc __ftprompt Far
-
- NewItem: Mov AX,42 ; Specify size of menu item
- Push AX ; Put on stack
- Call __XGrab ; Allocate RAM for it
- Add SP,2 ; Realign stack
-
- Mov BX,_MenuData ; Load local data segment
- Mov ES,BX ; Now put it in a segment reg
- Inc [ES:PrCount] ; Increment prompt counter
- Push [ES:PrCount] ; We'll need it later
-
- XChg AX,[ES:HeadOfs] ; Swap offsets
- XChg DX,[ES:HeadSeg] ; Swap segments
- LES BX,[ES:HeadPtr] ; Get pointer to new item
- Mov [MenuItem.NextOfs],AX ; Move old head pointer to newly
- Mov [MenuItem.NextSeg],DX ; allocated menu item
-
- GetInfo: Pop [MenuItem.PrNum] ; Get prompt counter back
- Push BP ; Save BP
- Mov BP,SP ; Set up stack reference
- Sub SP,4 ; Allocate local storage
- Mov [NodeOfs],BX ; Save pointer in ES:BX in local
- Mov [NodeSeg],ES ; storage -- avoids constant
- ; pushing and popping
-
- Mov AX,1 ; Specify first parameter
- Push AX ; Put on stack
- Call __ParNI ; Get prompt location
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.PrLoc],AX ; Store prompt location
-
- Mov AX,2 ; Specify second parameter
- Push AX ; Put on stack
- Call __ParClen ; Get length
- Add SP,2 ; Realign stack
-
- Push AX ; Put length on stack
- Call __XGrab ; Allocate RAM for copy
- Push DX ; Put copy pointer on stack for
- Push AX ; call to _ftStrDup
-
- Mov AX,2 ; Specify second parmeter
- Push AX ; Put on stack
- Call __ParC ; Get pointer to prompt
- Add SP,2 ; Realign stack
- Push DX ; Put prompt pointer on stack
- Push AX ; for call to _ftStrDup
-
- Call _ftStrDup ; Copy the prompt string
- Add SP,4 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Pop [MenuItem.PrOfs] ; Store prompt offset
- Pop [MenuItem.PrSeg] ; Store prompt offset
- Pop [MenuItem.PrLen] ; Store prompt length
- Call __XUnlock ; Tell VMM it's okay to let go
-
- Mov AX,3 ; Specify third parmeter
- Push AX ; Put on stack
- Call __ParNI ; Get prompt attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.PrAtt],AL ; Store attribute
-
- Mov AX,4 ; Specify fourth parameter
- Push AX ; Put on stack
- Call __ParNI ; Get message location
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.MsgLoc],AX ; Store location
-
- Mov AX,5 ; Specify fifth parameter
- Push AX ; Put on stack
- Call __ParClen ; Get length
- Add SP,2 ; Realign stack
-
- Push AX ; Put length on stack
- Call __XGrab ; Allocate RAM for copy
- Push DX ; Put copy pointer on stack for
- Push AX ; call to _ftStrDup
-
- Mov AX,5 ; Specify fifth parmeter
- Push AX ; Put on stack
- Call __ParC ; Get pointer to message
- Add SP,2 ; Realign stack
- Push DX ; Put message pointer on stack
- Push AX ; for call to _ftStrDup
-
- Call _ftStrDup ; Copy the prompt string
- Add SP,4 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Pop [MenuItem.MsgOfs] ; Store message offset
- Pop [MenuItem.MsgSeg] ; Store message segment
- Pop [MenuItem.MsgLen] ; Store message length
- Call __XUnlock ; Tell VMM it's okay to let go
- LES BX,[NodePtr] ; Restore node pointer
-
- Mov AX,[MenuItem.MsgLen] ; Get message length
- SHL AX,1 ; Multiply by two
- Push AX ; Put buffer size on stack
- Call __XGrab ; Allocate buffer
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.BufOfs],AX ; Store buffer offset
- Mov [MenuItem.BufSeg],DX ; Store buffer segment
-
- Mov AX,6 ; Specify sixth parmeter
- Push AX ; Put on stack
- Call __ParNI ; Get message attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.MsgAtt],AL ; Store attribute
-
- Mov AX,7 ; Specify seventh parameter
- Push AX ; Save on stack
- Call __ParNI ; Get hotkey attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.HKeyAtt],AL ; Store hotkey attribute
-
- Mov AX,8 ; Specify eighth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get hotkey location
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.HKeyLoc],AX ; Store hotkey location
-
- Mov AX,9 ; Specify ninth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get light bar attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.HKeyVal],AL ; Store hotkey value
-
- Mov AX,10 ; Specify tenth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get light bar attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.LBarAtt],AL ; Store light bar attribute
-
- Mov AX,11 ; Specify eleventh parameter
- Push AX ; Save on stack
- Call __ParNI ; Get hotkey/lightbar attribute
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.LBHKAtt],AL ; Store hotkey/lightbar attribute
-
- Mov AX,12 ; Specify twelfth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get up arrow target
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.Up],AX ; Store up arrow target
-
- Mov AX,13 ; Specify thirteenth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get down arrow target
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.Down],AX ; Store down arrow target
-
- Mov AX,14 ; Specify fourteenth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get right arrow target
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.Right],AX ; Store right arrow target
-
- Mov AX,15 ; Specify fifteenth parameter
- Push AX ; Save on stack
- Call __ParNI ; Get left arrow target
- Add SP,2 ; Realign stack
- LES BX,[NodePtr] ; Restore node pointer
- Mov [MenuItem.Left],AX ; Store left arrow target
-
- Call __Ret ; Return NIL
- Mov SP,BP ; Restore SP
- Pop BP ; Restore BP
- Ret
- Endp __ftprompt
-
-
-
- Proc _ftStrDup Near
-
- Push BP ; Save BP
- Mov BP,SP ; Set up stack reference
- Push DS ; Save DS
- Push SI ; Save SI
- Push DI ; Save DI
- CLD ; Ensure forward movement
-
- Mov SI,[Word Ptr BP + 4] ; Get source offset
- Mov DS,[Word Ptr BP + 6] ; Get source segment
- Mov DI,[Word Ptr BP + 8] ; Get target offset
- Mov ES,[Word Ptr BP + 10] ; Get target segment
- Mov CX,[Word Ptr BP + 12] ; Get string length
- Rep Movsb ; Copy string
-
- Pop DI ; Restore DI
- Pop SI ; Restore SI
- Pop DS ; Restore DS
- Pop BP ; Restore BP
- Ret
- Endp _ftStrDup
-
-
-
- Proc __ftMenuTo Far
-
- Push BP ; Save BP
- Mov BP,SP ; Set up stack reference
- Sub SP,24 ; Allocate space for locals
-
- Mov BX,_MenuData ; Get local data segment
- Mov ES,BX ; Load into segment register
- Mov BX,[ES:PrCount] ; Get prompt count
- Or BX,BX ; Any prompts yet?
- JNZ Okay ; Yes, so continue
- Mov AX,BX ; Get low word of return value
- Mov DX,BX ; Get high word of return value
- Jmp Done ; Exit with return of zero
-
- Okay: Mov [Last],BX ; Store prompt count in local
- Mov [NodeSeg],ES ; Store current node pointer
- Mov [NodeOfs],Offset ES:HeadOfs - 38
-
- GetDesiredPrompt:
- Mov AX,1 ; Specify first param
- Push AX ; Put on stack
- Call __ParNI ; Get parameter
- Add SP,2 ; Realign stack
- Mov CX,1 ; Set default value
- Or AX,AX ; Specified prompt = 0?
- JZ SetActivePrompt ; If so, use default
- Cmp AX,[Last] ; Check AX against prompt count
- JA SetActivePrompt ; If higher, use default
- Mov CX,AX ; Value okay, so use it
-
- SetActivePrompt:
- Mov [Active],CX ; Initalize active prompt
-
- GetFlagValues:
- Mov AX,2 ; Specify second param
- Push AX ; Put on stack
- Call __ParNI ; Get parameter
- Add SP,2 ; Realign stack
- Mov [Flags],AX ; Store flags
-
- GetSetKeyStuff:
- Xor AX,AX ; Request element count
- Push AX ; Put on stack
- Mov AX,3 ; Specify third param
- Push AX ; Put on stack
- Call __ParInfa ; Get setkey count
- Mov [SKCount],AX ; Store key count
- SHL AX,1 ; Multiply by by two
- Push AX ; Put result on stack
- Call __XGrab ; Allocate scan code table
- Add SP,6 ; Realign stack
- Mov [SKOfs],AX ; Store offset
- Mov [SKSeg],DX ; Store segment
- Mov CX,[SKCount] ; Set loop value
- JCXZ CheckForColor ; If no setkeys, skip next part
- GetNextScanCode:
- Push CX ; Put element # on stack
- Mov AX,3 ; Specify third param
- Push AX ; Put on stack
- Call __ParNI ; Get scancode
- Add SP,2 ; Realign stack
- Pop CX ; Restore CX
- Mov BX,CX ; Load element # into BX
- Dec BX ; Compensate for zero start
- SHL BX,1 ; Multiply by two
- Add BX,[SKOfs] ; Add offset
- Mov ES,[SKSeg] ; Load segment
- Mov [Word Ptr ES:BX],AX ; Store scancode
- Loop GetNextScanCode ; Do the next one
-
- CheckForColor:
- Mov [VideoBase],0B800h ; Default to color
- Xor AX,AX ; Clear AX
- Mov ES,AX ; Point ES to low memory
- Cmp [Word Ptr ES:463h],3D4h ; Color video?
- JE VideoTest ; If so, don't change to mono
- Mov [VideoBase],0B000h ; Change video base to mono
- And [Flags],NOT SnowFlag ; If mono, don't check for snow
- Jmp AllocateHotKeys ; Allocate hotkey table
-
- VideoTest:
- Mov AH,12h ; EGA/VGA BIOS call
- Mov BL,10h ; Set BL to test value
- Int 10h ; Call video BIOS
- Cmp BL,10h ; Did BL change?
- JE AllocateHotKeys ; No, so leave snow flag alone
- And [Flags],NOT SnowFlag ; EGA/VGA, set snow flag to false
-
- AllocateHotKeys:
- Push [Last] ; Put prompt count on stack
- Call __XGrab ; Allocate hotkey table
- Add SP,2 ; Realign stack
- Mov [TableSeg],DX ; Store segment
- Mov [TableOfs],AX ; Store offset
-
- MainLoopSetup:
- Push DS ; Save DS
- Push SI ; Save SI
- Push DI ; Save DI
- CLD ; Ensure forward movement
-
- Mov DX,3DAh ; Specify status port for later
- Mov CX,[Last] ; Initalize loop register
- LES BX,[NodePtr] ; Initialize ES:BX
-
- PromptLoopTop:
- Push CX ; Save loop counter
- LES BX,[NextPtr] ; Get pointer to next node
- Mov AL,[MenuItem.HKeyVal] ; Get hotkey value
- LDS SI,[TablePtr] ; Get pointer to hotkey table
- Add SI,CX ; Adjust offset
- Mov [Byte Ptr SI - 1],AL ; Store hotkey value
- LDS SI,[PrPtr] ; Get pointer to prompt
- Mov CX,[MenuItem.PrLen] ; Get prompt length
- JCXZ PromptLoopBottom ; If length = 0, jump to bottom
- Mov AH,[MenuItem.PrAtt] ; Get prompt attribute
- Push ES ; Save ES
- Mov DI,[MenuItem.PrLoc] ; Get screen location offset
- Mov ES,[VideoBase] ; Get screen location segment
-
- PromptRead:
- Lodsb ; Get a prompt character
- Test [Flags],SnowFlag ; See if snow-check in effect
- JZ PromptWrite ; If not, continue
- CheckSnow ; Wait for vertical retrace
-
- PromptWrite:
- Stosw ; Write character and attribute
- Loop PromptRead ; Do next character
- Pop ES ; Restore ES
-
- GetHotKeyAttr:
- Push ES ; Save ES again
- Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
- Inc DI ; Select attribute byte
- Mov AL,[MenuItem.HKeyAtt] ; Get hotkey attribute
- Mov ES,[VideoBase] ; Get video base segment
- Test [Flags],SnowFlag ; See if snow-check in effect
- JZ HotKeyAttr ; If not, continue
- CheckSnow ; Wait for vertical retrace
- HotKeyAttr:
- Stosb ; Change attribute byte
- Pop ES ; Restore ES
-
- PromptLoopBottom:
- Pop CX ; Restore loop counter
- Loop PromptLoopTop ; Do next prompt
-
- GetActivePrompt:
- LES BX,[NodePtr] ; Get pointer to last node
- Mov AX,[Active] ; Load current active item
-
- SearchLinkedList:
- LES BX,[NextPtr] ; Get pointer to next item
- Cmp AX,[MenuItem.PrNum] ; Found it yet?
- JNE SearchLinkedList ; Nope, so keep looking
-
- LightBarStuff:
- Push ES ; Save ES
- Mov AL,[MenuItem.LBarAtt] ; Get light bar attribute
- Mov CX,[MenuItem.PrLen] ; Get prompt length
- JCXZ LightBarEnd ; If length = 0, don't bother
- Mov DI,[MenuItem.PrLoc] ; Get prompt location
- Mov ES,[VideoBase] ; Load video base segment
- SetLightBarPtr:
- Inc DI ; Locate attribute byte
- Test [Flags],SnowFlag ; Check for snow?
- JZ WriteLightBar ; If not, continue
- CheckSnow ; Wait for vertical retrace
- WriteLightBar:
- Stosb ; Change attribute
- Loop SetLightBarPtr ; Do next byte
- LightBarEnd:
- Pop ES ; Restore ES
-
- GetLightBarHotKeyAttr:
- Push ES ; Save ES again
- Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
- Inc DI ; Select attribute byte
- Mov AL,[MenuItem.LBHKAtt] ; Get hotkey/lightbar attribute
- Mov ES,[VideoBase] ; Get video base segment
- Test [Flags],SnowFlag ; See if snow-check in effect
- JZ LightBarHotKeyAttr ; If not, continue
- CheckSnow ; Wait for vertical retrace
- LightBarHotKeyAttr:
- Stosb ; Change attribute byte
- Pop ES ; Restore ES
-
- BufferStuff:
- Test [Flags],SKFlag ; Is setkey flag set?
- JNZ MessageStuff ; If so, buffer already current
- Push ES ; Save ES
- Mov CX,[MenuItem.MsgLen] ; Get message length
- JCXZ MessageEnd ; If length = 0, don't bother
- Mov DS,[VideoBase] ; Set DS to video RAM
- Mov SI,[MenuItem.MsgLoc] ; Get message screen location
- LES DI,[BufPtr] ; Get pointer to buffer
- Test [Flags],SnowFlag ; Check for snow?
- JZ FastBuffer ; If not, use fast method
- SlowBuffer:
- CheckSnow ; Wait for vertical retrace
- Movsw ; Store character and attribute
- Loop SlowBuffer ; Do next character
- FastBuffer:
- Rep Movsw ; Store buffer
- Pop ES ; Restore ES
-
- MessageStuff:
- And [Flags],NOT SKFlag ; Turn setkey flag off
- Push ES ; Save ES
- Mov CX,[MenuItem.MsgLen] ; Get message length
- JCXZ MessageEnd ; If length = 0, no message
- LDS SI,[MsgPtr] ; Get pointer to message
- Mov AH,[MenuItem.MsgAtt] ; Get message attribute
- Mov DI,[MenuItem.MsgLoc] ; Get message location
- Mov ES,[VideoBase] ; Point ES to video RAM
- MessageRead:
- Lodsb ; Get a message byte
- Test [Flags],SnowFlag ; Check for snow?
- JZ MessageWrite ; Skip snow check
- CheckSnow ; Wait for vertical retrace
- MessageWrite:
- Stosw ; Write char and attribute
- Loop MessageRead ; Get next byte
- MessageEnd:
- Pop ES ; Restore ES
-
- CheckForHotKey:
- Test [Flags],HotFlag ; Hotkey pending?
- JZ GetNextKey ; If not, get next key
- Test [Flags],ColdFlag ; Hotkeys supposed to act cold?
- JNZ GetNextKey ; If so, continue
- Jmp ExitWithSelection ; We're finished
-
- GetNextKey:
- And [Flags],NOT HotFlag ; Make sure hotflag is off
- Mov AH,0 ; BIOS service -- keyboard input
- Int 16h ; Get a keystroke
- Or AL,AL ; Extended keystroke?
- JZ CheckForSetKey ; If so, continue
- Mov AH,0 ; Clear scan code -- ASCII in AL
-
- CheckForSetKey:
- Mov [ScanCode],AX ; Store most recent scancode
- Mov CX,[SKCount] ; Get setkey count
- JCXZ CheckEscapeKey ; If 0, no need for table check
- Push ES ; Save ES
- LES DI,[SetKeys] ; Get pointer to setkey table
- Repnz Scasw ; Look for extended scan code
- Pop ES ; Restore ES
- JNZ CheckEscapeKey ; Not found; check other keys
- Or [Flags],KeepFlag ; Turn keep flag on
- Jmp ExitWithSelection ; Go back to execute SET KEY
-
- CheckEscapeKey:
- Cmp AL,27 ; Escape key?
- JNE CheckEnterKey ; If not, check for enter
- Mov [Active],0 ; Set return value
- Jmp ExitWithSelection ; See if prompts need deallocated
-
- CheckEnterKey:
- Cmp AL,13 ; Enter key?
- JNE CheckUpLeftArrow ; If not, check arrow keys
- Jmp ExitWithSelection ; See if prompts need deallocated
-
- CheckUpLeftArrow:
- Mov CX,[MenuItem.Up] ; Get up arrow target
- Cmp AX,4800h ; Up arrow key?
- JE ProcessUpLeftArrow ; If so, process it
- Mov CX,[MenuItem.Left] ; Get left arrow target
- Cmp AX,4B00h ; Left arrow key?
- JE ProcessUpLeftArrow ; If so, process it
- Jmp CheckDownRightArrow ; Check for right or down arrow
- ProcessUpLeftArrow:
- Or CX,CX ; Default behavior requested?
- JZ UpLeftDefault ; If so, go to previous prompt
- Cmp CX,[Last] ; Target beyond range?
- JA UpLeftDefault ; If so, use default behavior
- Jmp GetNewPrompt ; Get new prompt
- UpLeftDefault:
- Mov CX,[Active] ; Load active prompt
- Cmp CX,1 ; First prompt active?
- JE UpLeftWrap ; If so, check for wrap
- Dec CX ; Decrement active prompt
- Jmp UpLeftExit ; Exit
- UpLeftWrap:
- Test [Flags],WrapFlag ; Wrapping requested?
- JZ UpLeftExit ; If not, exit
- Mov CX,[Last] ; Wrap to last prompt
- UpLeftExit:
- Jmp GetNewPrompt ; Get new prompt
-
- CheckDownRightArrow:
- Mov CX,[MenuItem.Down] ; Get down arrow target
- Cmp AX,5000h ; Down arrow key?
- JE ProcessRightDownArrow ; If so, process it
- Mov CX,[MenuItem.Right] ; Get right arrow target
- Cmp AX,4D00h ; Right arrow key?
- JE ProcessRightDownArrow ; If so, process it
- Jmp CheckHotKeyTable ; Check hotkey table
- ProcessRightDownArrow:
- Or CX,CX ; Default behavior requested?
- JZ DownRightDefault ; If so, go to previous prompt
- Cmp CX,[Last] ; Target beyond range?
- JA DownRightDefault ; If so, use default behavior
- Jmp GetNewPrompt ; Get new prompt
- DownRightDefault:
- Mov CX,[Active] ; Load active prompt
- Cmp CX,[Last] ; Last? prompt active?
- JE DownRightWrap ; If so, check for wrap
- Inc CX ; Increment active prompt
- Jmp DownRightExit ; Exit
- DownRightWrap:
- Test [Flags],WrapFlag ; Wrapping requested?
- JZ DownRightExit ; If not, exit
- Mov CX,1 ; Wrap to last prompt
- DownRightExit:
- Jmp GetNewPrompt ; Get new prompt
-
- CheckHotKeyTable:
- Push ES ; Save ES
- Cmp AL,'a' ; Check for lowercase a
- JB LoadHotKeyTable ; If below, don't convert
- Cmp AL,'z' ; Check for lowercase z
- JA LoadHotKeyTable ; If above, don't convert
- And AL,0DFh ; Convert to uppercase
- LoadHotKeyTable:
- LES DI,[TablePtr] ; Get pointer to table
- Add DI,[Active] ; Compensate for active prompt
- Mov CX,[Last] ; Get last prompt
- Cmp CX,[Active] ; At last prompt now?
- JE TableWrap ; If so, need to wrap
- Sub CX,[Active] ; # of prompts to end
- Repne Scasb ; Look for value
- JNZ TableWrap ; If not found, wrap to start
- Pop ES ; Restore ES
- Sub CX,[Last] ; Subtract prompt count
- Jmp EvaluateHotKey ; Evaluate hotkey
- TableWrap:
- LES DI,[TablePtr] ; Get pointer to table
- Mov CX,[Active] ; Set CX to active prompt
- Repne Scasb ; Look for value
- Pop ES ; Restore ES
- JNZ KeepSamePrompt ; Invalid key, get another one
- Sub CX,[Active] ; Subtract prompt offset
- EvaluateHotKey:
- Neg CX ; Get absolute value
- Or [Flags],HotFlag ; Turn hotflag on
- Jmp GetNewPrompt ; Get new prompt
-
- KeepSamePrompt:
- Jmp CheckForHotKey ; Discard key and get another
-
- GetNewPrompt:
- Cmp CX,[Active] ; Prompt changed?
- JE KeepSamePrompt ; If not, keep it
-
- Mov [Active],CX ; Set active prompt
- Push ES ; Save ES
- Mov AL,[MenuItem.PrAtt] ; Get prompt attribute
- Mov CX,[MenuItem.PrLen] ; Get prompt length
- JCXZ BarIsDead ; If length = 0, don't bother
- Mov DI,[MenuItem.PrLoc] ; Get prompt location
- Mov ES,[VideoBase] ; Load video base segment
- KillLightBar:
- Inc DI ; Locate attribute byte
- Test [Flags],SnowFlag ; Check for snow?
- JZ ResetPromptAttr ; If not, continue
- CheckSnow ; Wait for vertical retrace
- ResetPromptAttr:
- Stosb ; Change attribute
- Loop KillLightBar ; Do next byte
- Pop ES ; Restore ES
- Push ES ; Save ES again
- Mov DI,[MenuItem.HKeyLoc] ; Get hotkey location
- Inc DI ; Select attribute byte
- Mov AL,[MenuItem.HKeyAtt] ; Get hotkey attribute
- Mov ES,[VideoBase] ; Get video base segment
- Test [Flags],SnowFlag ; See if snow-check in effect
- JZ ResetHotKeyAttr ; If not, continue
- CheckSnow ; Wait for vertical retrace
- ResetHotKeyAttr:
- Stosb ; Change attribute byte
- BarIsDead:
- Pop ES ; Restore ES
-
- KillMessage:
- Push ES ; Save ES
- Mov CX,[MenuItem.MsgLen] ; Get message length
- JCXZ MessageIsDead ; If length = 0, don't bother
- LDS SI,[BufPtr] ; Get pointer to buffer
- Mov DI,[MenuItem.MsgLoc] ; Get message screen location
- Mov ES,[VideoBase] ; Set DS to video RAM
- Test [Flags],SnowFlag ; Check for snow?
- JZ QuickDeath ; If not, use fast method
- SlowDeath:
- CheckSnow ; Wait for vertical retrace
- Movsw ; Store character and attribute
- Loop SlowDeath ; Do next character
- QuickDeath:
- Rep Movsw ; Store buffer
- MessageIsDead:
- Pop ES ; Restore ES
- Jmp GetActivePrompt ; Go to top of loop
-
- Done: Push DX ; Put high word on stack
- Push AX ; Put low word on stack
- Call __RetNL ; Return value to app
- Mov SP,BP ; Restore SP
- Pop BP ; Restore BP
- Ret
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- ExitWithSelection:
- Pop DI ; Restore registers
- Pop SI
- Pop DS
- Call Near KillPrompts ; Kill prompts if needed
- Push [TableSeg] ; Hotkey table segment on stack
- Push [TableOfs] ; HotKey table offset on stack
- Call __XFree ; Free allocated RAM
- Push [SKSeg] ; Scancode table segment on stack
- Push [SKOfs] ; Scancode table offset on stack
- Call __XFree ; Free allocated RAM
- Mov AX,[Active] ; Set low order word
- Mov DX,[ScanCode] ; Set high order word
- Jmp Done
-
- KillPrompts:
- Test [Flags],KeepFlag ; Supposed to keep prompts?
- JZ PromptDeallocSetup ; If not, kill them
- RetN ; Near return
-
- PromptDeallocSetup:
- LES BX,[NodePtr] ; Get first node pointer
- Mov CX,[Last] ; Get loop value
- Mov [ES:PrCount],0 ; Reset prompt counter
- LES BX,[NextPtr] ; Get pointer to next item
-
- KillAPrompt:
- Mov [NodeSeg],ES ; Put ES:BX into local storage --
- Mov [NodeOfs],BX ; saves pushing and popping
- Push [MenuItem.NextSeg] ; Put next segment on stack
- Push [MenuItem.NextOfs] ; Put next offset on stack
-
- Push [MenuItem.PrSeg] ; Put prompt segment on stack
- Push [MenuItem.PrOfs] ; Put prompt offset on stack
- Call __XFree ; Free memory
- LES BX,[NodePtr] ; Restore node pointer
-
- Push [MenuItem.MsgSeg] ; Put message segment on stack
- Push [MenuItem.MsgOfs] ; Put message offset on stack
- Call __XFree ; Free memory
- LES BX,[NodePtr] ; Restore node pointer
-
- Push [MenuItem.BufSeg] ; Put buffer segment on stack
- Push [MenuItem.BufOfs] ; Put buffer offset on stack
- Call __XFree ; Free memory
- LES BX,[NodePtr] ; Restore node pointer
-
- Push ES ; Put node segment on stack
- Push BX ; Put node offset on stack
- Call __XFree ; Free memory
- Add SP,16 ; Realign stack
-
- Pop BX ; Get new node offset
- Pop ES ; Get new node segment
- Loop KillAPrompt ; Kill next node
- RetN ; Near return
-
- Endp __ftMenuTo
- Ends _NanFor
- End
-