kolibrios/programs/system/menu/trunk/menu.asm
Evgeny Grechnikov (Diamond) 0ecfb6aa5b @menu: bugfix: when child menu was closed on Esc, the same child could not be opened
git-svn-id: svn://kolibrios.org@728 a494cfbc-eb01-0410-851d-a64ba20cac60
2008-02-10 20:42:18 +00:00

578 lines
12 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;******************************************************************************
; MAIN MENU by lisovin@26.ru
; Some parts of code rewritten by Ivan Poddubny <ivan-yar@bk.ru>
;
; Compile with FASM for Menuet
;******************************************************************************
include "lang.inc"
include "..\..\..\macros.inc"
BTN_HEIGHT = 22
TXT_Y = (BTN_HEIGHT)/2-5
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x20000 ; memory for app
dd 0x20000-1 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
;******************************************************************************
;include "DEBUG.INC" ; debug macros
START: ; start of execution
mov eax, 48 ; load system colors
mov ebx, 3
mov ecx, sc
mov edx, sizeof.system_colors
mcall
mov eax, 70 ; load MENU.DAT
mov ebx, fileinfo
mcall
test eax, eax ; error ?
jz @f
cmp eax,6
jnz close
@@:
test ebx, ebx ; length = 0 ?
jz close
mov ecx, ebx
mov edi, mem_end
newsearch:
mov al, '#'
cld
repne scasb
test ecx, ecx ; if not found
jz close
call get_number
test ebx, ebx
jnz .number
cmp al, '#'
je search_end
.number:
shl ebx, 4
add ebx, menu_data ; pointer to process table
mov [ebx], edi
inc [processes]
jmp newsearch
search_end:
mov [end_pointer], edi
mov ebx, [processes]
dec ebx
shl ebx, 4
add ebx, menu_data
newprocess:
xor edx, edx
mov ecx, edi
sub ecx, [ebx]
mov al, 10
newsearch1:
std
repne scasb
test ecx, ecx
je endprocess
cmp [edi], byte 13
jne newsearch1
inc edx
jmp newsearch1
endprocess:
mov esi, ebx
add esi, 4
dec edx
mov [esi], dl
cmp ebx, menu_data
jbe search_end1
sub ebx, 16
jmp newprocess
search_end1:
mov eax, 14
mcall
sub ax, 20
mov [menu_data + y_end], ax
mov [menu_data + x_start], 5
mov al, [menu_data + rows]
mov [menu_data + cur_sel], al ; clear selection
mov [menu_data + prev_sel], al
mov [buffer], 0
thread:
mov eax, [buffer] ; identifier
shl eax, 4
add eax, menu_data
mov edi, eax
mov eax, 40 ; set event mask
mov ebx, 100111b ; mouse + button + key + redraw
mcall
call draw_window
still:
mov eax, 23 ; wait here for event
mov ebx, 5
mcall
test [close_now], 1 ; is close flag set?
jnz close
cmp eax, 1 ; redraw request ?
je red
cmp eax, 2 ; key pressed ?
je key
cmp eax, 3 ; button in buffer ?
je button
cmp eax, 6 ; mouse event ?
je mouse
cmp edi, menu_data
je still ; if main process-ignored
movzx ebx, [edi + parent] ; parent id
shl ebx, 4
add ebx, menu_data ; ebx = base of parent info
call backconvert ; get my id in al
cmp al, [ebx + child] ; if I'm not child of my parent, I shall die :)
jne close
jmp still
red: ; redraw
call draw_window
jmp still
key:
; mov eax, 2
mcall
mov al, [edi + rows] ; number of buttons
cmp ah, 178 ; KEY_UP
jne .noup
mov ah, [edi+cur_sel]
mov [edi+prev_sel], ah
dec byte [edi+cur_sel]
jnz redrawbut
mov [edi+cur_sel], al
jmp redrawbut
.noup:
cmp ah, 177 ; KEY_DOWN
jne .nodn
mov ah, [edi + cur_sel]
mov [edi + prev_sel], ah
inc [edi + cur_sel]
cmp [edi + cur_sel], al
jna redrawbut
mov [edi + cur_sel], 1
jmp redrawbut
.nodn:
cmp ah, 13 ; ENTER
jne .noenter
mov ah, [edi + cur_sel]
jmp button1
.noenter:
cmp ah, 27 ; ESC
jne still
jmp close
; include "DEBUG.INC"
button: ; BUTTON HANDLER
mov eax, 17 ; get id
mcall
button1:
mov esi, edi
push edi
mov edi, [edi + pointer]
; print "hello"
mov al, [esi + cur_sel]
mov [esi + prev_sel], al
mov [esi + cur_sel], ah
pushad
mov edi, esi
; dph eax
call draw_only_needed_buttons
popad
; look for the next line <ah> times; <ah> = button_id
push eax
.next_string:
call searchstartstring
dec ah
jnz .next_string
pop eax
mov ecx, 40
mov al, '/'
cld
repne scasb
test ecx, ecx ; if '/' not found
je searchexit
cmp [edi], byte '@' ; check for submenu
je runthread
dec edi
push edi ; pointer to start of filename
call searchstartstring ; search for next string
sub edi, 2 ; to last byte of string
mov ecx, edi
pop esi
sub ecx, esi
inc ecx ; length of filename
mov edi, fileinfo_start.name
rep movsb ; copy string
mov byte [edi], 0 ; store terminator
mov eax, 70 ; start program
mov ebx, fileinfo_start
mcall
; mcall 5,100
or [close_now], 1 ; set close flag
pop edi
mov [mousemask], 0
jmp close
searchexit:
pop edi
jmp still
runthread:
inc edi
push eax
call get_number ; get number of this process
pop eax
test ebx, ebx ; returned zero - main menu or not number
jz searchexit
mov al, bl
mov ebx, [processes]
dec bl
cmp al, bl
ja searchexit ; such process doesnt exist
cmp al, [esi + child]
je searchexit ; such process already exists
mov [esi + child], al ; this is my child
mov cx, [esi + x_start]
add cx, 141 ; new x_start in cx
movzx edx, al
shl edx, 4
add edx, menu_data ; edx points to child's base address
mov [edx + x_start], cx ; xstart for new thread
mov cx, [esi + y_end] ; y_end in cx
mov bl, [esi + rows] ; number of buttons in bl
sub bl, ah ; number of btn from bottom
movzx eax, al
mov [buffer], eax ; thread id in buffer
movzx ebx, bl
push edx
mov eax, BTN_HEIGHT
mul ebx
sub cx, ax ; new y_end for new thread
pop edx
mov [edx + y_end], cx ; store y_end
mov edi, esi
call backconvert ; get number of this process (al)
mov [edx + parent], al ; store number of parent process
mov al, [edx + rows]
mov [edx + cur_sel], al ; clear current selected element
mov [edx + prev_sel], al ; clear previous selected element
mov [edx + child], 0
cmp [thread_stack], 0x1e000
jne thread_stack_not_full
mov [thread_stack], 0xE000
thread_stack_not_full:
add [thread_stack], 0x2000 ; start new thread
mov eax, 51
mov ebx, 1
mov ecx, thread
mov edx, [thread_stack]
mcall
jmp searchexit
mouse: ; MOUSE EVENT HANDLER
mov eax, 37
mov ebx, 2
mcall
test eax, eax ; check buttons state
jnz click
mov eax, 37
mov ebx, 1
mcall
ror eax, 16 ; eax = [ Y | X ] relative to window
cmp ax, 140 ; pointer in window?
ja noinwindow
;  in window 
shr eax, 16 ; eax = [ 0 | Y ]
xor edx, edx
mov ebx, BTN_HEIGHT
div ebx
inc eax ; number of "button" in eax
movzx ebx, [edi + rows] ; total strings in ebx
cmp eax, ebx
ja noinwindow
cmp [edi + cur_sel], al
je noredrawbut
mov bl, [edi + cur_sel]
;;;;;;
cmp [edi + child], 0
jne noredrawbut
;;;;;;
mov [edi + cur_sel], al
mov [edi + prev_sel], bl
redrawbut:
call draw_only_needed_buttons
noredrawbut:
call backconvert
bts [mousemask], eax
jmp still
noinwindow:
call backconvert
btr [mousemask], eax
jmp still
click:
cmp [mousemask], 0 ; not in a window (i.e. menu)
je close
jmp still
close:
movzx ebx, [edi+parent] ; parent id
shl ebx, 4
add ebx, menu_data ; ebx = base of parent info
call backconvert
cmp [ebx + child], al ; if i am the child of my parent...
jnz @f
mov [ebx + child], -1 ; ...my parent now has no children
@@:
or eax, -1 ; close this thread
mov [edi + child], al ; my child is not mine
mcall
backconvert: ; convert from pointer to process id
mov eax, edi
sub eax, menu_data
shr eax, 4
ret
;==================================
; get_number
; load number from [edi] to ebx
;==================================
get_number:
push edi
xor eax, eax
xor ebx, ebx
.get_next_char:
mov al, [edi]
inc edi
cmp al, '0'
jb .finish
cmp al, '9'
ja .finish
sub al, '0'
imul ebx, 10
add ebx, eax
jmp .get_next_char
.finish:
pop edi
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax, 12 ; function 12:tell os about windowdraw
mov ebx, 1 ; 1, start of draw
mcall
movzx ebx, [edi + rows]
imul eax, ebx, BTN_HEIGHT ; eax = height of window
movzx ecx, [edi + y_end]
sub ecx, eax ; ecx = Y_START
shl ecx, 16
add ecx, eax ; ecx = [ Y_START | Y_SIZE ]
dec ecx
movzx ebx, [edi + x_start]
shl ebx, 16
mov bx, 140 ; ebx = [ X_START | X_SIZE ]
xor eax, eax ; function 0 : define and draw window
mov edx, 0x01000000 ; color of work area RRGGBB,8->color gl
mov esi, edx ; unmovable window
mcall
call draw_all_buttons
mov eax,12
mov ebx,2
mcall
ret
draw_all_buttons:
xor edx, edx
.new_button:
call draw_one_button
inc edx
cmp dl, [edi + rows]
jb .new_button
ret
draw_only_needed_buttons:
xor edx, edx
mov dl, [edi + cur_sel]
dec dl
call draw_one_button
mov dl, [edi + prev_sel]
dec dl
call draw_one_button
ret
draw_one_button:
; receives number of button in dl
push edx;ad
mov eax, 8
mov ebx, 140
movzx ecx, dl
imul ecx, BTN_HEIGHT
shl ecx, 16
add ecx, BTN_HEIGHT-1
; edx = button identifier
mov esi, [sc.work]
cmp esi, 0xdfdfdf
jb nocorrect
sub esi, 0x1b1b1b
nocorrect:
inc dl
cmp [edi + cur_sel], dl
jne .nohighlight
add esi, 0x1a1a1a
.nohighlight:
or edx, 0x20000000
mcall
movzx edx, dl
dec dl
imul ebx, edx, BTN_HEIGHT
add ebx, (4 shl 16) + TXT_Y
movzx ecx, dl
inc ecx
mov edx, [edi + pointer]
.findline:
cmp byte [edx], 13
je .linefound
inc edx
jmp .findline
.linefound:
inc edx
cmp byte [edx], 10
jne .findline
dec ecx
jnz .findline
mov ecx, [sc.work_text]
mov eax, 4
mov esi, 21
mcall
pop edx;ad
ret
searchstartstring:
mov ecx, 40
mov al, 13
cld
repne scasb
cmp byte [edi], 10
jne searchstartstring
ret
;*** DATA AREA ****************************************************************
thread_stack dd 0xE000
processes dd 0
fileinfo:
.subfunction dd 0 ; 0=READ
.start dd 0 ; start byte
.size_high dd 0 ; rezerved
.size dd 0x10000-mem_end ; blocks to read
.return dd mem_end ; return data pointer
.name:
db '/sys/MENU.DAT',0 ; ASCIIZ dir & filename
fileinfo_start:
.subfunction dd 7 ; 7=START APPLICATION
.flags dd 0 ; flags
.params dd 0x0 ; nop
.rezerved dd 0x0 ; nop
.rezerved_1 dd 0x0 ; nop
.name:
times 50 db ' '
I_END:
close_now dd ? ; close all processes immediately
end_pointer dd ?
buffer dd ?
mousemask dd ? ; mask for mouse pointer location
sc system_colors
menu_data:
rb 0x4000 ;x10000
virtual at 0 ; PROCESSES TABLE (located at menu_data)
pointer dd ? ; +0 pointer in file
rows db ? ; +4 numer of strings
x_start dw ? ; +5 x start
y_end dw ? ; +7 y end
child db ? ; +9 id of child menu
parent db ? ; +10 id of parent menu
cur_sel db ? ; +11 current selection
prev_sel db ? ; +12 previous selection
rb 16-$+1 ; [16 bytes per element]
end virtual
mem_end: