source: xtideuniversalbios/tags/XTIDE_Universal_BIOS_v1.1.0/Src/Libraries/menu/menuloop.asm@ 530

Last change on this file since 530 was 3, checked in by Tomi Tilli, 14 years ago
File size: 9.6 KB
Line 
1; File name : menuloop.asm
2; Project name : Menu library
3; Created date : 11.11.2009
4; Last update : 10.12.2009
5; Author : Tomi Tilli
6; Description : ASM library to menu system.
7; Contains event dispatching loop.
8
9;--------------- Equates -----------------------------
10
11; BIOS scan codes
12KEY_ENTER EQU 1Ch
13KEY_ESC EQU 01h
14KEY_UP EQU 48h
15KEY_DOWN EQU 50h
16KEY_PGUP EQU 49h
17KEY_PGDN EQU 51h
18KEY_HOME EQU 47h
19KEY_END EQU 4Fh
20CNT_MENU_KEYS EQU 8 ; Number of menukeys
21
22
23;-------------- Private global variables -------------
24; Section containing initialized data
25;SECTION .data
26
27
28;-------------- Public functions ---------------------
29; Section containing code
30SECTION .text
31
32
33;--------------------------------------------------------------------
34; Waits keyboard input, updates timeout and dispatch event for
35; user handler.
36; Parameters:
37; SS:BP: Ptr to MENUVARS
38; Returns:
39; Nothing
40; Corrupts registers:
41; AX, BX, CX, DX
42;--------------------------------------------------------------------
43ALIGN JUMP_ALIGN
44MenuLoop_Enter:
45 ; Get current time for timeout
46 call Menu_GetTime ; Get system time ticks to CX:DX
47 mov [bp+MENUVARS.wTimeLast], dx ; Store last read time
48
49 ; Check if menu operation should be continued
50ALIGN JUMP_ALIGN
51.CheckExit:
52 test BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT
53 jnz .Return ; Return if exit flag set
54
55 ; Check if keystroke available
56 call Keys_GetStroke ; Get keystroke to AX
57 jz .CheckTimeout ; If no keystroke, jump to check timeout
58 call MenuLoop_ProcessKey ; Convert keystroke to events
59
60 ; Check if timeout needs updating
61ALIGN JUMP_ALIGN
62.CheckTimeout:
63 cmp WORD [bp+MENUVARS.wTimeInit], 0 ; Timeout enabled?
64 jz .CheckExit ; If not, loop
65 call Menu_GetTime ; Get system time ticks to CX:DX
66 mov cx, dx ; Copy time loword to CX
67 sub dx, [bp+MENUVARS.wTimeLast] ; Has time changed?
68 je .CheckExit ; If not, loop
69
70 ; Update timeout
71 mov [bp+MENUVARS.wTimeLast], cx ; Store last update time
72 sub [bp+MENUVARS.wTimeout], dx ; Update timeout
73 ja .PrintTimeout ; If time left, just print new value
74 call MenuLoop_SendSelEvent ; Send selection event
75
76 ; Print timeout value
77ALIGN JUMP_ALIGN
78.PrintTimeout:
79 call MenuDraw_Timeout
80 xor dx, dx
81 call MenuCrsr_PointBelowBrdr
82 jmp .CheckExit
83
84ALIGN JUMP_ALIGN
85.Return:
86 ret
87
88
89;--------------------------------------------------------------------
90; Sends Menu event to user handler (MENUVARS.fnEvent).
91; MenuLoop_SendSelEvent Sends Menuitem Selected event to user event handler
92; MenuLoop_SendEvent Sends any event to user event handler
93; Parameters:
94; BX: Event code (MenuLoop_SendEvent only)
95; DX: Event parameter (event specific)
96; SS:BP: Ptr to MENUVARS
97; Returns:
98; AH: Event specific or unused
99; AL: 1=Event processed
100; 0=Event not processed (default action if any)
101; Corrupts registers:
102; BX, CX, DX
103;--------------------------------------------------------------------
104ALIGN JUMP_ALIGN
105MenuLoop_SendSelEvent:
106 mov bx, EVNT_MNU_SELSET
107ALIGN JUMP_ALIGN
108MenuLoop_SendEvent:
109 mov cx, [bp+MENUVARS.wItemSel]
110 call [bp+MENUVARS.fnEvent]
111 ret
112
113
114;-------------- Private functions ---------------------
115
116
117;--------------------------------------------------------------------
118; Processed menu key input.
119; Menu keys will be handled and other keys dispatched as key events.
120; Parameters:
121; AH: BIOS Scan Code for key
122; AL: ASCII character
123; SS:BP: Ptr to MENUVARS
124; Returns:
125; Nothing
126; Corrupts registers:
127; AX, BX, CX, DX
128;--------------------------------------------------------------------
129ALIGN JUMP_ALIGN
130MenuLoop_ProcessKey:
131 push es
132 push di
133
134 ; Check if wanted key
135 push cs
136 pop es ; Copy CS to ES
137 mov cx, CNT_MENU_KEYS ; Load number of menu keys
138 mov di, .rgbKeyToIdx ; Load offset to translation table
139 xchg al, ah ; Scan code to AL
140 cld ; SCASB to increment DI
141 repne scasb ; Compare [ES:DI] to AL until match
142 jne .Dispatch ; If not menukey, jump to dispatch
143
144 ; Jump to process menu key
145 mov di, CNT_MENU_KEYS-1 ; Convert CX...
146 sub di, cx ; ...to lookup index
147 shl di, 1 ; Prepare for word lookup
148 jmp [cs:di+.rgwMenuKeyJmp]
149
150 ; Dispatch key event
151ALIGN JUMP_ALIGN
152.Dispatch:
153 xchg al, ah ; Restore AX
154 mov bx, EVNT_MNU_KEY
155 mov dx, ax ; Copy keys to DX
156 call MenuLoop_SendEvent
157ALIGN JUMP_ALIGN
158.Return:
159 pop di
160 pop es
161 ret
162
163 ;;;;;;;;;;;;;;;;;;;;;
164 ; Menu key handlers ;
165 ;;;;;;;;;;;;;;;;;;;;;
166
167 ; ENTER pressed
168ALIGN JUMP_ALIGN
169.KeyEnter:
170 call MenuLoop_SendSelEvent ; Send selection event
171 jmp .Return
172
173 ; ESC pressed
174ALIGN JUMP_ALIGN
175.KeyEsc:
176 call Menu_Exit
177 jc .Return ; User cancelled exit
178 mov WORD [bp+MENUVARS.wItemSel], -1
179 jmp .Return
180
181 ; UP pressed
182ALIGN JUMP_ALIGN
183.KeyUp:
184%ifdef USE_MENU_DIALOGS
185 test BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW ; Message dialog mode?
186 jnz .TextScrollUp ; If so, go to text scrolling
187%endif
188 mov ax, [bp+MENUVARS.wItemSel] ; Load selected index
189 test ax, ax ; Already at top?
190 jz .KeyEnd ; If so, go to end
191 mov dx, ax ; Copy selected index to DX
192 dec ax ; Decrement menuitem index
193 mov [bp+MENUVARS.wItemSel], ax ; Store new index
194 cmp ax, [bp+MENUVARS.wItemTop] ; Need to scroll?
195 jae .DrawSelection ; If not, go to draw selection
196 dec WORD [bp+MENUVARS.wItemTop] ; Scroll
197 jmp .ScrollMenu
198
199%ifdef USE_MENU_DIALOGS
200ALIGN JUMP_ALIGN
201.TextScrollUp:
202 cmp WORD [bp+MENUVARS.wItemTop], 0 ; Already at the top?
203 jz .Return ; If so, return
204 dec WORD [bp+MENUVARS.wItemTop]
205 jmp .ScrollMenu
206%endif
207
208 ; DOWN pressed
209ALIGN JUMP_ALIGN
210.KeyDown:
211%ifdef USE_MENU_DIALOGS
212 test BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW ; Message dialog mode?
213 jnz .TextScrollDown ; If so, go to text scrolling
214%endif
215 mov ax, [bp+MENUVARS.wItemSel] ; Load selected index
216 mov dx, ax ; Copy selected index to DX
217 inc ax ; Increment menuitem index
218 cmp ax, [bp+MENUVARS.wItemCnt] ; Already at bottom?
219 je .KeyHome ; If so, go to beginning
220 mov [bp+MENUVARS.wItemSel], ax ; Store new menuitem index
221 eMOVZX bx, BYTE [bp+MENUVARS.bVisCnt] ; Load number of visible items
222 add bx, [bp+MENUVARS.wItemTop] ; BX to one past last visible index
223 cmp ax, bx ; Need to scroll?
224 jb .DrawSelection ; If not, go to draw selection
225 inc WORD [bp+MENUVARS.wItemTop] ; Scroll
226 jmp .ScrollMenu
227
228%ifdef USE_MENU_DIALOGS
229ALIGN JUMP_ALIGN
230.TextScrollDown:
231 eMOVZX ax, BYTE [bp+MENUVARS.bVisCnt] ; Load visible items
232 add ax, [bp+MENUVARS.wItemTop] ; Add topmost menuitem index
233 cmp ax, [bp+MENUVARS.wItemCnt] ; Already at the bottom?
234 jae .Return ; If so, return
235 inc WORD [bp+MENUVARS.wItemTop]
236 jmp .ScrollMenu
237%endif
238
239 ; PGUP pressed
240ALIGN JUMP_ALIGN
241.KeyPgUp:
242 mov ax, [bp+MENUVARS.wItemSel] ; Load selected index
243 div BYTE [bp+MENUVARS.bVisCnt] ; AL=Current page index
244 sub al, 1 ; Decrement page
245 jc .KeyHome ; Select first item if overflow
246 mul BYTE [bp+MENUVARS.bVisCnt] ; AX=Fist menuitem on page
247 mov [bp+MENUVARS.wItemSel], ax
248 mov [bp+MENUVARS.wItemTop], ax
249 jmp .ScrollMenu
250
251 ; PGDN pressed
252ALIGN JUMP_ALIGN
253.KeyPgDn:
254 mov ax, [bp+MENUVARS.wItemSel] ; Load selected index
255 div BYTE [bp+MENUVARS.bVisCnt] ; AL=Current page index
256 inc ax ; Increment page
257 mul BYTE [bp+MENUVARS.bVisCnt] ; AX=First menuitem on page
258 eMOVZX bx, BYTE [bp+MENUVARS.bVisCnt] ; Load number of visible items
259 add bx, ax ; BX now one past last visible
260 cmp bx, [bp+MENUVARS.wItemCnt] ; Went over last?
261 jae .KeyEnd ; If so, select last menuitem
262 mov [bp+MENUVARS.wItemSel], ax
263 mov [bp+MENUVARS.wItemTop], ax
264 jmp .ScrollMenu
265
266 ; HOME pressed
267ALIGN JUMP_ALIGN
268.KeyHome:
269 xor ax, ax
270 mov [bp+MENUVARS.wItemSel], ax
271 mov [bp+MENUVARS.wItemTop], ax
272 jmp .ScrollMenu
273
274 ; END pressed
275ALIGN JUMP_ALIGN
276.KeyEnd:
277 mov ax, [bp+MENUVARS.wItemCnt] ; Load number if menuitems
278 mov bx, ax ; Copy menuitem count to BX
279 dec ax ; Decrement for last index
280 mov [bp+MENUVARS.wItemSel], ax ; Store new selection
281 sub bl, [bp+MENUVARS.bVisCnt] ; BX to first menuitem to draw
282 sbb bh, 0
283 mov [bp+MENUVARS.wItemTop], bx ; Store first menuitem to draw
284 jnc .ScrollMenu
285 mov WORD [bp+MENUVARS.wItemTop], 0 ; Overflow, start with 0
286 ; Fall to .ScrollMenu
287
288 ; Menuitem selection changed, redraw all items
289ALIGN JUMP_ALIGN
290.ScrollMenu:
291 mov bx, EVNT_MMU_SELCHG
292 call MenuLoop_SendEvent
293 call Menu_RestartTimeout
294 xor cx, cx ; Invalidate...
295 dec cx ; ...all menuitems
296 mov dl, MFL_UPD_ITEM
297 call Menu_Invalidate
298 jmp .Return
299
300; Menuitem selection changed, only two items needs to be redrawn
301ALIGN JUMP_ALIGN
302.DrawSelection:
303 MINMAX_U ax, dx ; First menuitem to AX, next to DX
304 push dx ; Store second to draw
305 push ax ; Store first to draw
306 mov bx, EVNT_MMU_SELCHG
307 call MenuLoop_SendEvent
308 call Menu_RestartTimeout
309 pop cx ; First to draw to CX
310 call MenuCrsr_PointNthItem ; Set cursor position
311 call MenuDraw_Item ; Draw first menuitem
312 pop cx ; Second to draw to CX
313 call MenuDraw_Item ; Draw second menuitem
314 jmp .Return
315
316ALIGN WORD_ALIGN
317.rgwMenuKeyJmp:
318 dw .KeyEnter ; KEY_ENTER
319 dw .KeyEsc ; KEY_ESC
320 dw .KeyUp ; KEY_UP
321 dw .KeyDown ; KEY_DOWN
322 dw .KeyPgUp ; KEY_PGUP
323 dw .KeyPgDn ; KEY_PGDN
324 dw .KeyHome ; KEY_HOME
325 dw .KeyEnd ; KEY_END
326; Scan code to jump index translation table
327.rgbKeyToIdx:
328 db KEY_ENTER, KEY_ESC, KEY_UP, KEY_DOWN,
329 db KEY_PGUP, KEY_PGDN, KEY_HOME, KEY_END
Note: See TracBrowser for help on using the repository browser.