; int __stdcall DialogBox(DLGTEMPLATE* dlg, void* DlgProc); ; int __stdcall DlgProc(int msg, int param1, int param2); virtual at 0 dlgtemplate: .flags dd ? .x dd ? .y dd ? .width dd ? .height dd ? .border_size_x dd ? .border_size_y dd ? .title dd ? .main_color db ? .border_color db ? .header_color db ? db ? ; align end virtual DialogBox: pushad ; some checks mov ebx, [esp+20h+4] mov eax, [ebx+dlgtemplate.x] cmp eax, 1 jl .sizeerr add eax, [ebx+dlgtemplate.width] cmp eax, [cur_width] jge .sizeerr mov eax, [ebx+dlgtemplate.y] cmp eax, 1 jl .sizeerr add eax, [ebx+dlgtemplate.height] cmp eax, [cur_height] jge .sizeerr cmp [ebx+dlgtemplate.border_size_x], 1 jl .sizeerr cmp [ebx+dlgtemplate.border_size_y], 1 jge .sizeok .sizeerr: popad or eax, -1 ret 8 .sizeok: ; allocate memory for data under dialog mov eax, [ebx+dlgtemplate.width] add eax, [ebx+dlgtemplate.border_size_x] add eax, [ebx+dlgtemplate.border_size_x] inc eax inc eax mov edx, [ebx+dlgtemplate.height] add edx, [ebx+dlgtemplate.border_size_y] add edx, [ebx+dlgtemplate.border_size_y] inc edx mul edx add eax, eax call mf_alloc test eax, eax jnz @f ; TODO: add error message popad or eax, -1 ret 8 @@: mov ebp, eax ; save data mov eax, [ebx+dlgtemplate.y] add eax, [ebx+dlgtemplate.height] add eax, [ebx+dlgtemplate.border_size_y] inc eax push eax mov eax, [ebx+dlgtemplate.x] add eax, [ebx+dlgtemplate.width] add eax, [ebx+dlgtemplate.border_size_x] inc eax inc eax push eax mov eax, [ebx+dlgtemplate.y] sub eax, [ebx+dlgtemplate.border_size_y] push eax mov eax, [ebx+dlgtemplate.x] sub eax, [ebx+dlgtemplate.border_size_x] push eax call save_console_data ; draw shadow mov eax, [ebx+dlgtemplate.x] sub eax, [ebx+dlgtemplate.border_size_x] ja @f xor eax, eax @@: push eax ; save real window left inc eax inc eax mov edx, [ebx+dlgtemplate.y] sub edx, [ebx+dlgtemplate.border_size_y] ja @f xor edx, edx @@: push edx ; save real window top inc edx call get_console_ptr mov ecx, [ebx+dlgtemplate.y] add ecx, [ebx+dlgtemplate.height] add ecx, [ebx+dlgtemplate.border_size_y] inc ecx cmp ecx, [cur_height] jb @f mov ecx, [cur_height] @@: sub ecx, edx mov edx, ecx mov ecx, [ebx+dlgtemplate.x] add ecx, [ebx+dlgtemplate.width] add ecx, [ebx+dlgtemplate.border_size_x] inc ecx inc ecx cmp ecx, [cur_width] jb @f mov ecx, [cur_width] @@: sub ecx, eax mov eax, ecx .shadow_loop: mov ecx, eax push edi .sl1: inc edi test byte [edi], 0x0F jnz @f or byte [edi], 8 @@: and byte [edi], 0x0F inc edi loop .sl1 pop edi add edi, [cur_width] add edi, [cur_width] dec edx jnz .shadow_loop ; draw area background pop edx pop eax call get_console_ptr mov ecx, [ebx+dlgtemplate.x] add ecx, [ebx+dlgtemplate.width] add ecx, [ebx+dlgtemplate.border_size_x] cmp ecx, [cur_width] jb @f mov ecx, [cur_width] @@: sub ecx, eax mov esi, ecx mov ecx, [ebx+dlgtemplate.y] add ecx, [ebx+dlgtemplate.height] add ecx, [ebx+dlgtemplate.border_size_y] cmp ecx, [cur_height] jb @f mov ecx, [cur_height] @@: sub ecx, edx mov edx, ecx mov al, ' ' mov ah, [ebx+dlgtemplate.border_color] .1: mov ecx, esi push edi rep stosw pop edi add edi, [cur_width] add edi, [cur_width] dec edx jnz .1 ; draw border mov eax, [ebx+dlgtemplate.x] dec eax mov edx, [ebx+dlgtemplate.y] dec edx call get_console_ptr mov edx, [ebx+dlgtemplate.height] inc edx inc edx mov ah, [ebx+dlgtemplate.border_color] push ebx mov ebx, [ebx+dlgtemplate.width] inc ebx inc ebx call draw_border pop ebx ; draw header mov esi, [ebx+dlgtemplate.title] test esi, esi jz .noheader cmp byte [esi], 0 jz .noheader push esi @@: lodsb test al, al jnz @b mov eax, esi pop esi sub eax, esi inc eax ; eax = фышэр чруюыютър + 2 mov ecx, [ebx+dlgtemplate.width] cmp eax, ecx jbe .fullhea sub ecx, 5 jb .noheader xor edx, edx jmp .drawhea .fullhea: mov edx, ecx sub edx, eax shr edx, 1 .drawhea: mov eax, [ebx+dlgtemplate.x] add eax, edx mov edx, [ebx+dlgtemplate.y] dec edx call get_console_ptr mov ah, [ebx+dlgtemplate.header_color] mov al, ' ' stosw dec ecx .2: jecxz .3 lodsb test al, al jz .4 stosw jmp .2 .3: mov al, '.' stosw stosw stosw .4: mov al, ' ' stosw .noheader: ; draw window background mov eax, [ebx+dlgtemplate.x] mov edx, [ebx+dlgtemplate.y] call get_console_ptr mov ah, [ebx+dlgtemplate.main_color] mov al, ' ' mov edx, [ebx+dlgtemplate.height] @@: mov ecx, [ebx+dlgtemplate.width] push edi rep stosw pop edi add edi, [cur_width] add edi, [cur_width] dec edx jnz @b ; send redraw message mov eax, [esp+20h+8] push ebx ebp push 0 push 0 push 1 call eax call draw_image pop ebp ebx ; message loop .event: push 10 pop eax int 40h dec eax jz .redraw dec eax jz .key or eax, -1 int 40h .redraw: push ebx ebp call draw_window pop ebp ebx jmp .event .key: mov al, 2 int 40h shr eax, 8 cmp al, 0xE0 jnz @f mov [bWasE0], 1 jmp .event @@: xchg ah, [bWasE0] cmp al, 0x1D jz .ctrl_down cmp al, 0x9D jz .ctrl_up cmp al, 0x2A jz .lshift_down cmp al, 0xAA jz .lshift_up cmp al, 0x36 jz .rshift_down cmp al, 0xB6 jz .rshift_up cmp al, 0x38 jz .alt_down cmp al, 0xB8 jz .alt_up mov ecx, [esp+20h+8] push ebx ebp push 0 push eax push 2 call ecx pop ebp ebx test eax, eax jz .event mov [esp+28], eax jmp .exit .ctrl_down: test ah, ah jnz .rctrl_down or [ctrlstate], 4 jmp .event .rctrl_down: or [ctrlstate], 8 jmp .event .ctrl_up: test ah, ah jnz .rctrl_up and [ctrlstate], not 4 jmp .event .rctrl_up: and [ctrlstate], not 8 jmp .event .lshift_down: test ah, ah jnz @f or [ctrlstate], 1 @@: jmp .event .lshift_up: test ah, ah jnz @b and [ctrlstate], not 1 jmp @b .rshift_down: or [ctrlstate], 2 jmp .event .rshift_up: and [ctrlstate], not 2 jmp .event .alt_down: test ah, ah jnz .ralt_down or [ctrlstate], 0x10 jmp .event .ralt_down: or [ctrlstate], 0x20 jmp .event .alt_up: test ah, ah jnz .ralt_up and [ctrlstate], not 0x10 jmp .event .ralt_up: and [ctrlstate], not 0x20 jmp .event .exit: ; restore data mov eax, [ebx+dlgtemplate.y] add eax, [ebx+dlgtemplate.height] add eax, [ebx+dlgtemplate.border_size_y] inc eax push eax mov eax, [ebx+dlgtemplate.x] add eax, [ebx+dlgtemplate.width] add eax, [ebx+dlgtemplate.border_size_x] inc eax inc eax push eax mov eax, [ebx+dlgtemplate.y] sub eax, [ebx+dlgtemplate.border_size_y] push eax mov eax, [ebx+dlgtemplate.x] sub eax, [ebx+dlgtemplate.border_size_x] push eax call restore_console_data call draw_keybar mov eax, ebp call mf_free call draw_image popad ret 8 save_console_data: cmp dword [esp+4], 0 jge @f and dword [esp+4], 0 @@: cmp dword [esp+8], 0 jge @f and dword [esp+8], 0 @@: mov eax, [esp+12] cmp eax, [cur_width] jbe @f mov eax, [cur_width] @@: sub eax, [esp+4] ja @f ret 16 @@: mov [esp+12], eax mov eax, [esp+16] cmp eax, [cur_height] jbe @f mov eax, [cur_height] @@: sub eax, [esp+8] ja @f ret 16 @@: mov [esp+16], eax mov eax, [esp+4] mov edx, [esp+8] call get_console_ptr mov esi, edi mov edi, ebp .l: mov ecx, [esp+12] push esi shr ecx, 1 rep movsd adc ecx, ecx rep movsw pop esi add esi, [cur_width] add esi, [cur_width] dec dword [esp+16] jnz .l ret 16 restore_console_data: cmp dword [esp+4], 0 jge @f and dword [esp+4], 0 @@: cmp dword [esp+8], 0 jge @f and dword [esp+8], 0 @@: mov eax, [esp+12] cmp eax, [cur_width] jbe @f mov eax, [cur_width] @@: sub eax, [esp+4] ja @f ret 16 @@: mov [esp+12], eax mov eax, [esp+16] cmp eax, [cur_height] jbe @f mov eax, [cur_height] @@: sub eax, [esp+8] ja @f ret 16 @@: mov [esp+16], eax mov eax, [esp+4] mov edx, [esp+8] call get_console_ptr mov esi, ebp .l: mov ecx, [esp+12] push edi shr ecx, 1 rep movsd adc ecx, ecx rep movsw pop edi add edi, [cur_width] add edi, [cur_width] dec dword [esp+16] jnz .l ret 16 ; int __stdcall menu(void* variants, const char* title, unsigned flags); ; variants указывает на текущий элемент в двусвязном линейном списке menu: pop eax push [cur_height] push [cur_width] push 0 push 0 push eax ; int __stdcall menu_centered_in(unsigned left, unsigned top, unsigned width, unsigned height, ; void* variants, const char* title, unsigned flags); menu_centered_in: pushad mov eax, 56 ; 36 bytes for dlgtemplate + additional: ; +36: dd cur_variant ; +40: dd num_variants ; +44: dd begin_variant ; +48: dd end_variant ; +52: dd cur_variant_idx call mf_alloc test eax, eax jnz @f .ret_bad: popad or eax, -1 ret 28 @@: mov ebx, eax mov eax, 1 test byte [esp+20h+28], 1 jz @f mov al, 3 @@: mov [ebx+dlgtemplate.border_size_x], eax inc eax shr eax, 1 mov [ebx+dlgtemplate.border_size_y], eax ; Находим ширину и высоту окна xor eax, eax xor ecx, ecx mov esi, [esp+20h+20] mov [ebx+36], esi and dword [ebx+52], 0 @@: cmp dword [esi+4], 0 jz .find_width mov esi, [esi+4] inc dword [ebx+52] jmp @b .find_width: mov [ebx+44], esi add esi, 8 push esi xor edx, edx .fw1: cmp byte [esi], '&' jnz @f mov dl, 1 @@: inc esi cmp byte [esi-1], 0 jnz .fw1 sub esi, [esp] sub esi, edx dec esi cmp eax, esi ja @f mov eax, esi @@: inc ecx pop esi mov esi, [esi-8] test esi, esi jnz .find_width add eax, 3 add eax, [ebx+dlgtemplate.border_size_x] add eax, [ebx+dlgtemplate.border_size_x] cmp eax, [cur_width] jb @f mov eax, [cur_width] @@: sub eax, [ebx+dlgtemplate.border_size_x] sub eax, [ebx+dlgtemplate.border_size_x] mov [ebx+dlgtemplate.width], eax mov [ebx+dlgtemplate.height], ecx mov [ebx+40], ecx sub eax, [esp+20h+12] neg eax sar eax, 1 add eax, [esp+20h+4] cmp eax, [ebx+dlgtemplate.border_size_x] jge @f mov eax, [ebx+dlgtemplate.border_size_x] @@: push eax add eax, [ebx+dlgtemplate.width] add eax, [ebx+dlgtemplate.border_size_x] cmp eax, [cur_width] jbe @f pop eax mov eax, [cur_width] sub eax, [ebx+dlgtemplate.width] sub eax, [ebx+dlgtemplate.border_size_x] push eax @@: pop [ebx+dlgtemplate.x] sub ecx, [esp+20h+16] neg ecx sar ecx, 1 add ecx, [esp+20h+8] cmp ecx, [ebx+dlgtemplate.border_size_y] jge @f mov ecx, [ebx+dlgtemplate.border_size_y] @@: push ecx add ecx, [ebx+dlgtemplate.height] add ecx, [ebx+dlgtemplate.border_size_y] cmp ecx, [cur_height] jbe @f pop ecx mov ecx, [cur_height] sub ecx, [ebx+dlgtemplate.height] sub ecx, [ebx+dlgtemplate.border_size_y] push ecx @@: pop [ebx+dlgtemplate.y] mov eax, [cur_height] sub eax, 6 cmp [ebx+dlgtemplate.height], eax jbe .small_height mov [ebx+dlgtemplate.height], eax mov [ebx+dlgtemplate.y], 3 .small_height: mov ecx, [ebx+dlgtemplate.height] mov eax, [ebx+36] mov [ebx+44], eax dec ecx jz .skip push ecx @@: cmp dword [eax+4], 0 jz @f mov eax, [eax+4] loop @b @@: mov [ebx+44], eax pop ecx .loop: mov eax, [eax] loop .loop .skip: mov [ebx+48], eax mov eax, [esp+20h+24] mov [ebx+dlgtemplate.title], eax mov al, [menu_normal_color] mov [ebx+dlgtemplate.main_color], al mov al, [menu_border_color] mov [ebx+dlgtemplate.border_color], al mov al, [menu_header_color] mov [ebx+dlgtemplate.header_color], al push MenuDlgProc push ebx call DialogBox mov [esp+28], eax mov eax, ebx call mf_free popad ret 28 MenuDlgProc: mov eax, [esp+4] cmp al, 1 jz .draw cmp al, 2 jz .key ret 12 .draw: call .dodraw ret 12 .key: mov al, [esp+8] cmp al, 0x48 jz .prev cmp al, 0x4B jz .prev cmp al, 0x4D jz .next cmp al, 0x50 jz .next cmp al, 0x1C jz .enter cmp al, 1 jz .esc cmp al, 0x47 jz .home cmp al, 0x4F jz .end cmp al, 0x51 jz .pgdn cmp al, 0x49 jz .pgup mov edx, [ebx+36] @@: cmp dword [edx+4], 0 jz @f mov edx, [edx+4] jmp @b @@: .l: lea esi, [edx+7] @@: inc esi cmp byte [esi], 0 jz .n cmp byte [esi], '&' jnz @b movzx ecx, byte [esi+1] cmp [ascii2scan+ecx], al jnz .n mov eax, edx ret 12 .n: mov edx, [edx] test edx, edx jnz .l .ret: xor eax, eax ret 12 .pgup: mov eax, [ebx+36] mov ecx, [ebx+dlgtemplate.height] .pgupl: cmp dword [eax+4], 0 jz .posret call .line_prev loop .pgupl jmp .posret .prev: mov eax, [ebx+36] cmp dword [eax+4], 0 jz .end call .line_prev .posret: mov [ebx+36], eax .redraw: call .dodraw call draw_image xor eax, eax ret 12 .next: mov eax, [ebx+36] cmp dword [eax], 0 jz .home call .line_next jmp .posret .pgdn: mov eax, [ebx+36] mov ecx, [ebx+dlgtemplate.height] .pgdnl: cmp dword [eax], 0 jz .posret call .line_next loop .pgdnl jmp .posret .home: mov eax, [ebx+36] @@: cmp dword [eax+4], 0 jz @f mov eax, [eax+4] jmp @b @@: mov [ebx+44], eax push eax mov ecx, [ebx+dlgtemplate.height] dec ecx jz .h1 .h2: mov eax, [eax] loop .h2 .h1: mov [ebx+48], eax pop eax and dword [ebx+52], 0 jmp .posret .end: mov eax, [ebx+36] @@: cmp dword [eax], 0 jz @f mov eax, [eax] jmp @b @@: mov [ebx+48], eax push eax mov ecx, [ebx+dlgtemplate.height] dec ecx jz .e1 .e2: mov eax, [eax+4] loop .e2 .e1: mov [ebx+44], eax mov eax, [ebx+40] dec eax mov [ebx+52], eax pop eax jmp .posret .esc: or eax, -1 ret 12 .enter: mov eax, [ebx+36] ret 12 .line_prev: cmp eax, [ebx+44] jnz @f mov edx, [ebx+44] mov edx, [edx+4] mov [ebx+44], edx mov edx, [ebx+48] mov edx, [edx+4] mov [ebx+48], edx @@: mov eax, [eax+4] dec dword [ebx+52] ret .line_next: cmp eax, [ebx+48] jnz @f mov edx, [ebx+44] mov edx, [edx] mov [ebx+44], edx mov edx, [ebx+48] mov edx, [edx] mov [ebx+48], edx @@: mov eax, [eax] inc dword [ebx+52] ret .dodraw: mov eax, [ebx+dlgtemplate.x] mov edx, [ebx+dlgtemplate.y] call get_console_ptr mov esi, [ebx+44] .0: xor edx, edx mov ah, [menu_selected_color] cmp esi, [ebx+36] jz @f mov ah, [menu_normal_color] @@: push edi mov ecx, [ebx+dlgtemplate.width] mov al, ' ' stosw dec ecx stosw dec ecx dec ecx push esi add esi, 8 @@: lodsb test al, al jz @f cmp al, '&' jnz .noamp test dl, dl jnz .noamp mov dl, 1 lodsb push eax mov ah, [menu_selected_highlight_color] push ecx mov ecx, [esp+8] cmp ecx, [ebx+36] pop ecx jz .amp1 mov ah, [menu_highlight_color] .amp1: stosw pop eax jmp .amp2 .noamp: stosw .amp2: loop @b mov al, ' ' cmp byte [esi], 0 jnz .1 lodsb jmp .1 @@: mov al, ' ' .1: stosw mov al, ' ' rep stosw pop esi edi add edi, [cur_width] add edi, [cur_width] cmp esi, [ebx+48] jz @f mov esi, [esi] test esi, esi jnz .0 @@: ; Линейка прокрутки mov ecx, [ebx+dlgtemplate.height] cmp ecx, [ebx+40] jz .noscrollbar sub ecx, 2 jbe .noscrollbar mov eax, [ebx+52] mul ecx div dword [ebx+40] push eax mov eax, [ebx+dlgtemplate.x] add eax, [ebx+dlgtemplate.width] mov edx, [ebx+dlgtemplate.y] call get_console_ptr pop edx inc edx mov al, 0x1E mov ah, [menu_scrollbar_color] mov [edi], ax add edi, [cur_width] add edi, [cur_width] .2: mov al, 0xB2 dec edx jz @f mov al, 0xB0 @@: mov [edi], ax add edi, [cur_width] add edi, [cur_width] loop .2 mov al, 0x1F stosw .noscrollbar: ret