use32
        db      'MENUET01'
        dd      1
        dd      start
        dd      i_end
memsize dd      mem
        dd      stacktop
        dd      0, 0

include 'lang.inc'
include 'font.inc'
include 'sort.inc'
include 'kglobals.inc'
include 'memalloc.inc'
include 'dialogs.inc'
include 'viewer.inc'

start:
        mov     eax, mem
        call    mf_init
        call    draw_window
        push    66
        pop     eax
        push    1
        pop     ebx
        mov     ecx, ebx
        int     40h     ; set keyboard mode to scancodes
        call    init_console
        mov     esi, def_left_dir
        mov     edi, panel1_dir
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
@@:
        mov     esi, def_right_dir
        mov     edi, panel2_dir
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        mov     eax, 304
        mov     [panel1_nfa], eax
        mov     [panel2_nfa], eax
        mov     [panel1_files], buf1
        mov     [panel2_files], buf2
        mov     [panel1_sortmode], 0    ; sort by name
        mov     [panel2_sortmode], 0
        mov     [num_screens], 1
        mov     eax, 8
        call    mf_alloc
        mov     [screens], eax
        mov     ecx, panels_vtable
        mov     [eax], ecx
        mov     [active_screen_vtable], ecx
        call    draw_keybar
        call    draw_cmdbar
        mov     ebp, panel1_data
        call    read_folder
        call    draw_panel
        mov     ebp, panel2_data
        call    read_folder
        call    draw_panel
event:
        push    10
        pop     eax
        int     40h
        dec     eax
        jz      redraw
        dec     eax
        jz      key
; button - we have only one button, close
exit:
        or      eax, -1
        int     40h
redraw:
        mov     al, 9
        mov     ebx, procinfo
        or      ecx, -1
        int     40h
; test if rolled up
; height of rolled up window is [skinh]+3
        mov     eax, [ebx+46]
        sub     eax, [skinh]
        cmp     eax, 5
        ja      @f
        mov     al, 12
        push    1
        pop     ebx
        int     0x40
        xor     eax, eax
; ebx, ecx, edi are ignored by function 0 after first redraw
        mov     edx, 0x13000000
        int     0x40
        mov     al, 12
        inc     ebx
        int     0x40
        jmp     event
@@:
        xor     ecx, ecx
        mov     eax, [ebx+42]
        sub     eax, 5*2
        jae     @f
        xor     eax, eax
@@:
        cdq
        mov     esi, font_width
        div     esi
        cmp     eax, 54
        jae     @f
        mov     al, 54
        mov     ch, 1
@@:
        cmp     eax, 255
        jbe     @f
        mov     eax, 255
        mov     ch, 1
@@:
        cmp     eax, [cur_width]
        mov     [cur_width], eax
        setnz   cl
        or      cl, ch
        test    edx, edx
        setnz   ch
        or      cl, ch
        mov     eax, [ebx+46]
        sub     eax, [skinh]
        sub     eax, 5
        jns     @f
        xor     eax, eax
@@:
        cdq
        mov     esi, font_height
        div     esi
        cmp     eax, 8
        jae     @f
        mov     al, 8
        mov     cl, 1
@@:
        cmp     eax, 255
        jbe     @f
        mov     eax, 255
        mov     cl, 1
@@:
        cmp     eax, [cur_height]
        mov     [cur_height], eax
        setnz   ch
        or      cl, ch
        test    edx, edx
        setnz   ch
        test    cx, cx
        jz      @f
        mov     eax, [MemForImage]
        call    mf_free
        and     [MemForImage], 0
        call    init_console
        push    67
        pop     eax
        or      ebx, -1
        or      ecx, -1
        mov     edx, [cur_width]
        imul    edx, font_width
        add     edx, 5*2
        mov     esi, [cur_height]
        imul    esi, font_height
        add     esi, [skinh]
        add     esi, 5
        int     40h
        call    draw_window
        call    draw_keybar
        mov     ebp, [active_screen_data]
        mov     eax, [active_screen_vtable]
        call    dword [eax+screen_vtable.OnRedraw]
        jmp     event
@@:
        call    draw_window
        jmp     event
key:
        mov     al, 2
        int     40h
        test    al, al
        jnz     event
        xchg    al, ah
        cmp     al, 0xE0
        jnz     @f
        mov     [bWasE0], 1
        jmp     event
@@:
        xchg    ah, [bWasE0]
        mov     ebp, [active_screen_data]
        mov     edx, [active_screen_vtable]
        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
        call    [edx+screen_vtable.OnKey]
        jmp     event
.ctrl_down:
        test    ah, ah
        jnz     .rctrl_down
        or      [ctrlstate], 4
        jmp     .keybar
.rctrl_down:
        or      [ctrlstate], 8
        jmp     .keybar
.ctrl_up:
        test    ah, ah
        jnz     .rctrl_up
        and     [ctrlstate], not 4
        jmp     .keybar
.rctrl_up:
        and     [ctrlstate], not 8
.keybar:
        call    draw_keybar
        call    draw_image
@@:     jmp     event
.lshift_down:
; ignore E0 2A sequence
; e.g. arrow keys with NumLock on generate sequence E0 2A E0 xx / E0 xx+80 E0 AA
; where xx is scancode, so we can safely ignore E0 2A
        test    ah, ah
        jnz     @b
        or      [ctrlstate], 1
        jmp     .keybar
.lshift_up:
; ignore E0 AA sequence
        test    ah, ah
        jnz     @b
        and     [ctrlstate], not 1
        jmp     .keybar
.rshift_down:
        or      [ctrlstate], 2
        jmp     .keybar
.rshift_up:
        and     [ctrlstate], not 2
        jmp     .keybar
.alt_down:
        test    ah, ah
        jnz     .ralt_down
        or      [ctrlstate], 0x10
        jmp     .keybar
.ralt_down:
        or      [ctrlstate], 0x20
        jmp     .keybar
.alt_up:
        test    ah, ah
        jnz     .ralt_up
        and     [ctrlstate], not 0x10
        jmp     .keybar
.ralt_up:
        and     [ctrlstate], not 0x20
        jmp     .keybar

process_ctrl_keys:
        cmp     byte [esi], 0
        jz      .done
        push    ecx
        cmp     al, [esi]
        jz      .check
.cont:
        pop     ecx
        add     esi, 8
        jmp     process_ctrl_keys
.done:
        stc
        ret
.check:
        mov     cl, 0
        call    .check_ctrlkey
        jc      .cont
        mov     cl, 2
        call    .check_ctrlkey
        jc      .cont
        mov     cl, 4
        call    .check_ctrlkey
        jc      .cont
        pop     ecx
        call    dword [esi+4]
        clc
        ret
.check_ctrlkey:
        push    eax edx
        movzx   edx, [ctrlstate]
        shr     edx, cl
        add     cl, cl
        movzx   eax, word [esi+2]
        shr     eax, cl
        and     eax, 15
        cmp     al, ctrlkey_tests_num
        jae     .fail
        xchg    eax, edx
        and     al, 3
        call    [ctrlkey_tests + edx*4]
        cmp     al, 1
        pop     edx eax
        ret
.fail:
        stc
        pop     edx eax
        ret

ctrlkey_test0:
        test    al, al
        setz    al
        ret
ctrlkey_test1:
        test    al, al
        setnp   al
        ret
ctrlkey_test2:
        cmp     al, 3
        setz    al
        ret
ctrlkey_test3:
        cmp     al, 1
        setz    al
        ret
ctrlkey_test4:
        cmp     al, 2
        setz    al
        ret

; TODO: add "no memory" error handling
new_screen:
        call    mf_alloc
        test    eax, eax
        jnz     @f
        ret
@@:
        mov     ebp, eax
        mov     ebx, [num_screens]
        inc     ebx
        shl     ebx, 3
        mov     eax, [screens]
        call    mf_realloc
        test    eax, eax
        jnz     @f
        mov     eax, ebp
        call    mf_free
        xor     eax, eax
        ret
@@:
        mov     [screens], eax
        inc     [num_screens]
        mov     [eax+ebx-8], edx
        mov     [eax+ebx-4], ebp
        mov     eax, [num_screens]
        dec     eax
        mov     [active_screen], eax
        mov     [active_screen_vtable], edx
        mov     [active_screen_data], ebp
        jmp     draw_keybar

next_screen:
        mov     eax, [active_screen]
        inc     eax
        cmp     eax, [num_screens]
        jnz     @f
        xor     eax, eax
@@:     mov     [active_screen], eax
        jmp     change_screen

delete_active_screen:
        mov     edi, [screens]
        mov     eax, [active_screen]
        shl     eax, 3
        add     edi, eax
        push    dword [edi+4]
        lea     esi, [edi+8]
        mov     ecx, [num_screens]
        sub     ecx, [active_screen]
        dec     ecx
        add     ecx, ecx
        rep     movsd
        dec     [num_screens]
        mov     ebx, [num_screens]
        shl     ebx, 3
        mov     eax, [screens]
        call    mf_realloc
        pop     eax
        call    mf_free
        and     [active_screen], 0

change_screen:
        pusha
        mov     eax, [active_screen]
        mov     esi, [screens]
        mov     ebp, [esi+eax*8+4]
        mov     eax, [esi+eax*8]
        mov     [active_screen_vtable], eax
        mov     [active_screen_data], ebp
        call    draw_keybar
        call    [eax+screen_vtable.OnRedraw]
        popa
        ret

F12:
        mov     eax, [cur_width]
        add     eax, 8
        mov     esi, eax
        mul     [num_screens]
        call    mf_alloc
        test    eax, eax
        jnz     @f
        ret
@@:
        mov     ebx, eax
        mov     edi, eax
        xor     ecx, ecx
.next:
        xor     eax, eax
        stosd
        inc     ecx
        cmp     ecx, [num_screens]
        jz      @f
        lea     eax, [edi+esi-4]
        mov     dword [edi-4], eax
@@:
        xor     eax, eax
        stosd
        dec     ecx
        jz      @f
        lea     eax, [edi-8]
        sub     eax, esi
        mov     dword [edi-4], eax
@@:
        mov     al, '&'
        stosb
        cmp     ecx, 36
        jae     .noletter
        lea     eax, [ecx+'0']
        cmp     al, '9'
        jbe     @f
        add     al, 7
@@:
        stosb
        mov     al, '.'
        stosb
        jmp     .letter_done
.noletter:
        mov     al, ' '
        stosb
        stosb
.letter_done:
        mov     al, ' '
        stosb
        pushad
        mov     eax, [screens]
        mov     ebp, [eax+ecx*8+4]
        mov     eax, [eax+ecx*8]
        mov     ecx, [cur_width]
        sub     ecx, 12
        call    [eax + screen_vtable.getname]
        popad
        sub     edi, 4
        add     edi, [cur_width]
        inc     ecx
        cmp     ecx, [num_screens]
        jb      .next
        mov     eax, [active_screen]
        mul     esi
        add     eax, ebx
        push    1
        push    aScreens
        push    eax
        call    menu
        cmp     eax, -1
        jz      @f
        sub     eax, ebx
        div     esi
        mov     [active_screen], eax
@@:
        mov     eax, ebx
        call    mf_free
        jmp     change_screen

panels_OnKey:
        mov     ebp, [active_panel]
        mov     ecx, [ebp + panel1_index - panel1_data]
        mov     edx, [ebp + panel1_start - panel1_data]
        mov     ebx, [ebp + panel1_colst - panel1_data]
        add     ebx, edx
        mov     esi, panels_ctrlkeys
        jmp     process_ctrl_keys
.ret:
        ret
.up:
        jecxz   .ret
        dec     ecx
        mov     [ebp + panel1_index - panel1_data], ecx
        cmp     ecx, edx
        jae     .done_redraw
        mov     [ebp + panel1_start - panel1_data], ecx
.done_redraw:
;        call    draw_panel
;        ret
        jmp     draw_panel
.down:
        inc     ecx
        cmp     ecx, [ebp + panel1_numfiles - panel1_data]
        jae     .ret
        mov     [ebp + panel1_index - panel1_data], ecx
        cmp     ecx, ebx
        jb      .done_redraw
        sub     ecx, [ebp + panel1_colst - panel1_data]
        inc     ecx
        mov     [ebp + panel1_start - panel1_data], ecx
        jmp     .done_redraw
.left:
        jecxz   .ret
        sub     ecx, [ebp + panel1_colsz - panel1_data]
        jae     @f
        xor     ecx, ecx
@@:
        mov     [ebp + panel1_index - panel1_data], ecx
        cmp     ecx, edx
        jae     .done_redraw
        sub     edx, [ebp + panel1_colsz - panel1_data]
        jae     @f
        xor     edx, edx
@@:
        mov     [ebp + panel1_start - panel1_data], edx
        jmp     .done_redraw
.right:
        add     ecx, [ebp + panel1_colsz - panel1_data]
        cmp     ecx, [ebp + panel1_numfiles - panel1_data]
        jb      @f
        mov     ecx, [ebp + panel1_numfiles - panel1_data]
        dec     ecx
@@:
        mov     [ebp + panel1_index - panel1_data], ecx
        cmp     ecx, ebx
        jb      .done_redraw
        add     ebx, [ebp + panel1_colsz - panel1_data]
        cmp     ebx, [ebp + panel1_numfiles - panel1_data]
        jbe     @f
        mov     ebx, [ebp + panel1_numfiles - panel1_data]
@@:
        sub     ebx, [ebp + panel1_colst - panel1_data]
        jae     @f
        xor     ebx, ebx
@@:
        mov     [ebp + panel1_start - panel1_data], ebx
        jmp     .done_redraw
.tab:
        xor     [active_panel], panel1_data xor panel2_data
        call    draw_cmdbar
        call    draw_panel
        mov     ebp, [active_panel]
        jmp     .done_redraw
.home:
        and     [ebp + panel1_start - panel1_data], 0
        and     [ebp + panel1_index - panel1_data], 0
        jmp     .done_redraw
.end:
        mov     eax, [ebp + panel1_numfiles - panel1_data]
        dec     eax
        mov     [ebp + panel1_index - panel1_data], eax
        inc     eax
        sub     eax, [ebp + panel1_colst - panel1_data]
        jae     @f
        xor     eax, eax
@@:
        mov     [ebp + panel1_start - panel1_data], eax
        jmp     .done_redraw
.enter:
        mov     eax, [ebp + panel1_files - panel1_data]
        mov     ecx, [eax+ecx*4]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     ecx, [ecx+eax*4+32]
        add     ecx, [ebp + panel1_files - panel1_data]
        test    byte [ecx], 10h
        jnz     .enter_folder
; find extension
        lea     esi, [ecx+40]
        push    esi
@@:
        lodsb
        test    al, al
        jnz     @b
@@:
        dec     esi
        cmp     byte [esi], '.'
        jz      .found_ext
        cmp     esi, [esp]
        ja      @b
        jmp     .run_app
.found_ext:
        inc     esi
        mov     edi, associations
@@:
        push    esi edi
        mov     edi, [edi]
        call    strcmpi
        pop     edi esi
        jz      .run_association
        add     edi, 8
        cmp     edi, associations_end
        jb      @b
        jmp     .run_app
.run_association:
        mov     [execparams], execdata
        mov     eax, [edi+4]
        mov     [execptr], eax
        jmp     .dorun
.run_app:
        mov     [execptr], execdata
        and     [execparams], 0
.dorun:
        pop     esi
        lea     esi, [ebp + panel1_dir - panel1_data]
        mov     edi, execdata
; TODO: add overflow check
@@:
        lodsb
        test    al, al
        jz      @f
        stosb
        jmp     @b
@@:
        lea     esi, [ecx+40]
        mov     al, '/'
        stosb
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        push    70
        pop     eax
        mov     ebx, execinfo
        int     40h
        ret
.enter_folder:
        lea     esi, [ecx+40]
        cmp     word [esi], '..'
        jnz     @f
        cmp     byte [esi+2], 0
        jz      .dotdot
@@:
        lea     edi, [ebp + panel1_dir - panel1_data]
        mov     al, 0
        or      ecx, -1
        repnz   scasb
        dec     edi
        mov     al, '/'
        cmp     [edi-1], al
        jz      @f
        stosb
@@:
; TODO: add buffer overflow check
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
.reread:
        call    read_folder
.done_cmdbar:
        call    draw_cmdbar
        jmp     .done_redraw
.dotdot:
        lea     edi, [ebp + panel1_dir - panel1_data]
        mov     al, 0
        or      ecx, -1
        repnz   scasb
        dec     edi
        mov     al, '/'
        std
        repnz   scasb
        cld
        inc     edi
        mov     byte [edi], 0
        inc     edi
        push    edi
        call    read_folder
        pop     edi
        mov     edx, [ebp + panel1_files - panel1_data]
        mov     ecx, [ebp + panel1_numfiles - panel1_data]
.scanloop:
        mov     esi, [edx]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     esi, [esi+eax*4+32+40]
        add     esi, [ebp + panel1_files - panel1_data]
        push    esi edi
@@:
        lodsb
        call    match_symbol
        jnz     @f
        inc     edi
        test    al, al
        jnz     @b
@@:
        pop     edi esi
        jz      .scanfound
        add     edx, 4
        loop    .scanloop
        jmp     .scandone
.scanfound:
        sub     edx, [ebp + panel1_files - panel1_data]
        shr     edx, 2
        mov     [ebp + panel1_index - panel1_data], edx
        sub     edx, [ebp + panel1_colst - panel1_data]
        jb      .scandone
        inc     edx
        mov     [ebp + panel1_start - panel1_data], edx
.scandone:
        jmp     .done_cmdbar
.ctrl_f39:
        sub     al, 0x3D
        add     al, al
        mov     ah, [ebp + panel1_sortmode - panel1_data]
        and     ah, 0xFE
        cmp     al, ah
        jnz     @f
        and     [ebp + panel1_sortmode - panel1_data], 1
        or      al, [ebp + panel1_sortmode - panel1_data]
        xor     al, 1
@@:
        mov     [ebp + panel1_sortmode - panel1_data], al
        mov     eax, [ebp + panel1_index - panel1_data]
        mov     ecx, [ebp + panel1_files - panel1_data]
        push    dword [ecx+eax*4]
        push    ecx
        call    sort_files
        pop     edi
        pop     eax
        or      ecx, -1
        repnz   scasd
        not     ecx
        dec     ecx
        mov     [ebp + panel1_index - panel1_data], ecx
        sub     ecx, [ebp + panel1_start - panel1_data]
        jb      .less_start
        sub     ecx, [ebp + panel1_colst - panel1_data]
        jae     .gr_end
@@:     jmp     .done_redraw
.less_start:
        add     [ebp + panel1_start - panel1_data], ecx
        jmp     @b
.gr_end:
        inc     ecx
        add     [ebp + panel1_start - panel1_data], ecx
        jmp     @b
.alt_f12:
        mov     ebp, panel1_data
        cmp     al, 0x3B
        jz      @f
        mov     ebp, panel2_data
@@:
; get drives list
        mov     ebx, dirinfo
        mov     [ebx+dirinfo.size-dirinfo], 1
        mov     [ebx+dirinfo.dirdata-dirinfo], driveinfo
        mov     [ebx+dirinfo.name-dirinfo], tmpname
        mov     byte [tmpname], '/'
        xor     ecx, ecx
.drive_loop_e:
        mov     byte [tmpname+1], 0
        push    70
        pop     eax
        int     40h
        mov     ebx, dirinfo
        test    eax, eax
        jnz     .drive_loop_e_done
        mov     esi, driveinfo+32+40
        mov     edi, tmpname+1
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        push    [ebx+dirinfo.first-dirinfo]
        and     [ebx+dirinfo.first-dirinfo], 0
.drive_loop_i:
        push    70
        pop     eax
        int     40h
        mov     ebx, dirinfo
        test    eax, eax
        jnz     .drive_loop_i_done
        mov     eax, 32+8
        call    mf_alloc
        test    eax, eax
        jz      .drive_loop_i_done
        jecxz   @f
        mov     [ecx], eax
@@:
        and     dword [eax], 0
        mov     [eax+4], ecx
        mov     ecx, eax
        lea     edi, [eax+8]
        mov     esi, tmpname
@@:
        lodsb
        test    al, al
        jz      @f
        stosb
        jmp     @b
@@:
        mov     esi, driveinfo+32+40
        mov     al, '/'
        stosb
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        inc     [ebx+dirinfo.first-dirinfo]
        jmp     .drive_loop_i
.drive_loop_i_done:
        pop     [ebx+dirinfo.first-dirinfo]
        inc     [ebx+dirinfo.first-dirinfo]
        jmp     .drive_loop_e
.drive_loop_e_done:
        and     [ebx+dirinfo.first-dirinfo], 0
        lea     edi, [ebp + panel1_dir - panel1_data]
.find_cur_drive_loop:
        push    edi
        lea     esi, [ecx+8]
@@:
        lodsb
        test    al, al
        jz      .cur_drive_found
        call    match_symbol
        jnz     @f
        inc     edi
        jmp     @b
@@:
        cmp     dword [ecx+4], 0
        jz      @f
        pop     edi
        mov     ecx, [ecx+4]
        jmp     .find_cur_drive_loop
@@:
.cur_drive_found:
        pop     edi
        push    1
        push    aDrive
        push    ecx
        mov     eax, [ebp + panel1_height - panel1_data]
        sub     eax, 2
        jae     @f
        add     eax, 2
@@:
        push    eax
        push    [ebp + panel1_width - panel1_data]
        push    [ebp + panel1_top - panel1_data]
        push    [ebp + panel1_left - panel1_data]
        call    menu_centered_in
        cmp     eax, -1
        jz      .ret2
        lea     esi, [eax+8]
        lea     edi, [ebp + panel1_dir - panel1_data]
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
@@:
        cmp     dword [ecx+4], 0
        jz      @f
        mov     ecx, [ecx+4]
        jmp     @b
@@:
        mov     eax, ecx
        mov     ecx, [ecx]
        call    mf_free
        test    ecx, ecx
        jnz     @b
        call    read_folder
        jmp     .done_redraw
.f3:
        call    view_file
.ret2:
        ret
.f8:
        mov     eax, [ebp + panel1_files - panel1_data]
        mov     ecx, [eax+ecx*4]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     ecx, [ecx+eax*4+32]
        add     ecx, [ebp + panel1_files - panel1_data]
        lea     esi, [ebp + panel1_dir - panel1_data]
        mov     edi, execdata
@@:
        lodsb
        test    al, al
        jz      @f
        stosb
        jmp     @b
@@:
        lea     esi, [ecx+40]
        mov     al, '/'
        stosb
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        push    70
        pop     eax
        mov     ebx, delinfo
        int     0x40
.ctrl_r:
; Rescan panel
;       call    read_folder
;       jmp     .done_redraw
        mov     eax, [ebp + panel1_index - panel1_data]
        push    eax
        mov     ecx, [ebp + panel1_files - panel1_data]
        mov     ecx, [ecx+eax*4]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     esi, [ecx+eax*4+32+40]
        add     esi, [ebp + panel1_files - panel1_data]
        mov     edi, saved_file_name
@@:
        lodsb
        stosb
        test    al, al
        jnz     @b
        push    [ebp + panel1_start - panel1_data]
        call    read_folder
        pop     [ebp + panel1_start - panel1_data]
        pop     [ebp + panel1_index - panel1_data]
        or      eax, -1
@@:
        inc     eax
        cmp     eax, [ebp + panel1_numfiles - panel1_data]
        jae     .ctrl_r.notfound
        mov     esi, [ebp + panel1_nfa - panel1_data]
        mov     ecx, [ebp + panel1_files - panel1_data]
        lea     esi, [ecx+esi*4+32+40]
        add     esi, [ecx+eax*4]
        mov     edi, saved_file_name
        call    strcmpi
        jnz     @b
.ctrl_r.found:
        mov     [ebp + panel1_index - panel1_data], eax
.ctrl_r.notfound:
        mov     eax, [ebp + panel1_numfiles - panel1_data]
        dec     eax
        cmp     [ebp + panel1_index - panel1_data], eax
        jbe     @f
        mov     [ebp + panel1_index - panel1_data], eax
@@:
        mov     eax, [ebp + panel1_index - panel1_data]
        cmp     [ebp + panel1_start - panel1_data], eax
        jbe     @f
        mov     [ebp + panel1_start - panel1_data], eax
@@:
        inc     eax
        sub     eax, [ebp + panel1_colst - panel1_data]
        jae     @f
        xor     eax, eax
@@:
        cmp     [ebp + panel1_start - panel1_data], eax
        jae     @f
        mov     [ebp + panel1_start - panel1_data], eax
@@:
        mov     eax, [ebp + panel1_numfiles - panel1_data]
        sub     eax, [ebp + panel1_colst - panel1_data]
        jbe     @f
        cmp     [ebp + panel1_start - panel1_data], eax
        jbe     @f
        mov     [ebp + panel1_start - panel1_data], eax
@@:
        jmp     .done_redraw

panels_OnRedraw:
        call    draw_cmdbar
        mov     ebp, panel1_data
        call    draw_panel
        mov     ebp, panel2_data
        call    draw_panel
        ret

init_console:
        mov     ax, 0720h
        mov     ecx, [cur_width]
        imul    ecx, [cur_height]
        mov     edi, console_data
        rep     stosw
        and     [panel1_left], 0
        and     [panel1_top], 0
        and     [panel2_top], 0
        mov     eax, [cur_width]
        inc     eax
        shr     eax, 1
        mov     [panel1_width], eax
        mov     [panel2_left], eax
        sub     eax, [cur_width]
        neg     eax
        mov     [panel2_width], eax
        mov     eax, [cur_height]
        dec     eax
        dec     eax
        mov     [panel1_height], eax
        mov     [panel2_height], eax
        ret

panels_getname:
if lang eq ru
        mov     eax, 'Пане'
        stosd
        mov     eax, 'ли  '
        stosd
        mov     eax, '    '
        stosd
        stosb
else
        mov     eax, 'Pane'
        stosd
        mov     eax, 'ls  '
        stosd
        mov     eax, '    '
        stosd
        stosb
end if
        sub     ecx, 13
        mov     ebp, [active_panel]
        lea     esi, [ebp + panel1_dir - panel1_data]
        push    3
        pop     edx
@@:
        lodsb
        stosb
        dec     ecx
        test    al, al
        jz      @f
        cmp     al, '/'
        jnz     @b
        dec     edx
        jnz     @b
@@:
        test    al, al
        jnz     @f
        dec     esi
        dec     edi
@@:
        push    esi
@@:
        lodsb
        test    al, al
        jnz     @b
        dec     esi
        mov     ebx, esi
        sub     ebx, [esp]
        dec     esi
        push    esi
        mov     edx, [ebp + panel1_files - panel1_data]
        mov     esi, [ebp + panel1_index - panel1_data]
        mov     esi, [edx+esi*4]
        add     esi, edx
        mov     edx, [ebp + panel1_nfa - panel1_data]
        lea     esi, [esi+edx*4+32+40]
        push    esi
@@:
        lodsb
        test    al, al
        jnz     @b
        add     ebx, esi
        sub     ebx, [esp]
        dec     esi
        cmp     ebx, ecx
        jbe     @f
        mov     al, '.'
        stosb
        stosb
        stosb
        sub     ecx, 3
        mov     ebx, ecx
@@:
        add     edi, ebx
        inc     ecx
        std
@@:
        movsb
        dec     ecx
        jz      .nodir
        cmp     esi, [esp]
        jae     @b
        mov     al, '/'
        stosb
        dec     ecx
        jz      .nodir
        mov     esi, [esp+4]
@@:
        cmp     esi, [esp+8]
        jb      .nodir
        movsb
        loop    @b
.nodir:
        cld
        pop     eax
        pop     eax
        pop     eax
        ret

draw_window:
        push    12
        pop     eax
        push    1
        pop     ebx
        int     40h
        mov     al, 48
        mov     bl, 4
        int     40h
        mov     [skinh], eax
        mov     ebx, [cur_width]
        imul    ebx, font_width
        add     ebx, 100*65536 + 5*2
        mov     ecx, [cur_height]
        imul    ecx, font_height
        lea     ecx, [eax+ecx+5+100*65536]
        xor     eax, eax
        mov     edx, 0x13000000
        mov     edi, header
        int     40h
        mov     al, 48
        push    3
        pop     ebx
        mov     ecx, std_colors
        push    40
        pop     edx
        int     40h
;        mov     bl, 7
;        int     40h
;        xor     ax, ax
;        shr     ebx, 16
;        or      ebx, eax
;        mov     ecx, [std_colors+16]
;        mov     edx, header
;        push    header.length
;        pop     esi
;        push    4
;        pop     eax
;        int     40h
        xor     ecx, ecx
        call    draw_image
        push    12
        pop     eax
        push    2
        pop     ebx
        int     40h
        ret

draw_image.nomem:
        mov     al, 13
        xor     edx, edx
        mov     ebx, [cur_width]
        imul    ebx, font_width
        add     ebx, 5*65536
        mov     ecx, [skinh-2]
        mov     cx, word [cur_height]
        imul    cx, font_height
        int     40h
        mov     al, 4
        mov     ebx, 32*65536+32
        mov     ecx, 0xFFFFFF
        mov     edx, nomem_draw
        push    nomem_draw.size
        pop     esi
        int     40h
        ret

draw_image:
        cmp     [MemForImage], 0
        jnz     .allocated
; allocate memory for image
        mov     eax, [cur_width]
        imul    eax, [cur_height]
        imul    eax, font_width*font_height*3
        call    mf_alloc
        test    eax, eax
        jz      draw_image.nomem
        mov     [MemForImage], eax
.allocated:
        mov     edi, [MemForImage]
        mov     esi, console_data
        mov     ecx, [cur_height]
.lh:
        push    ecx
        mov     ecx, [cur_width]
.lw:
        push    ecx edi
        xor     eax, eax
        mov     al, [esi+1]
        and     al, 0xF
        mov     ebx, [console_colors + eax*4]   ; цвет текста
        mov     al, [esi+1]
        shr     al, 4
        mov     ebp, [console_colors + eax*4]   ; цвет фона
        lodsb
        inc     esi
if font_width > 8
        lea     edx, [eax+eax+font]
else
        lea     edx, [eax+font]
end if
        mov     ecx, font_height
.sh:
        push    ecx edi
        xor     ecx, ecx
.sw:
        mov     eax, ebx
        bt      [edx], ecx
        jc      @f
        mov     eax, ebp
@@:
        stosw
        shr     eax, 16
        stosb
        inc     ecx
        cmp     ecx, font_width
        jb      .sw
        pop     edi ecx
        mov     eax, [cur_width]
        imul    eax, font_width*3
        add     edi, eax
if font_width > 8
        add     edx, 256*2
else
        add     edx, 256
end if
        loop    .sh
        pop     edi ecx
        add     edi, font_width*3
        loop    .lw
        mov     eax, [cur_width]
        imul    eax, (font_height-1)*font_width*3
        add     edi, eax
        pop     ecx
        loop    .lh
        push    7
        pop     eax
        mov     ebx, [MemForImage]
        mov     ecx, [cur_width]
        imul    ecx, font_width*10000h
        mov     cx, word [cur_height]
        imul    cx, font_height
        mov     edx, [skinh]
        add     edx, 5*10000h
        int     40h
        ret

get_console_ptr:
; in: eax=x, edx=y
; out: edi->console data
        push    edx
        imul    edx, [cur_width]
        add     edx, eax
        lea     edi, [console_data + edx*2]
        pop     edx
        ret

draw_keybar:
        pushad
        xor     eax, eax
        test    [ctrlstate], 3
        jz      @f
        inc     eax
@@:
        test    [ctrlstate], 0xC
        jz      @f
        or      al, 2
@@:
        test    [ctrlstate], 0x30
        jz      @f
        or      al, 4
@@:
        imul    eax, 6*12
        mov     esi, [active_screen_vtable]
        mov     esi, [esi+screen_vtable.keybar]
        add     esi, eax
        xor     ecx, ecx
        inc     ecx
        xor     eax, eax
        mov     edx, [cur_height]
        dec     edx
        call    get_console_ptr
        push    6
        pop     ebx
        mov     eax, [cur_width]
        sub     eax, 11+9+3*2+6
        cmp     eax, 7*11
        jl      @f
        cdq
        mov     bl, 11
        div     ebx
        mov     ebx, eax
@@:
        xor     edx, edx
.l:
        add     edx, 7
        cmp     cl, 10
        jb      @f
        inc     edx
@@:
        cmp     edx, [cur_width]
        ja      .ret
        cmp     cl, 10
        jae     .twodig
        lea     eax, [ecx+'0']
        stosb
        mov     al, [keybar_number_color]
        stosb
        jmp     .cmn
.twodig:
        mov     al, cl
        cbw
        div     [_10]
        add     al, '0'
        stosb
        mov     al, [keybar_number_color]
        stosb
        xchg    al, ah
        add     al, '0'
        stosw
.cmn:
        mov     ah, [keybar_name_color]
        push    ecx
        mov     cl, 6
@@:
        lodsb
        stosw
        loop    @b
        mov     al, ' '
        lea     ecx, [ebx-6]
        cmp     byte [esp], 12
        jz      .ret_pop
        add     edx, ecx
        rep     stosw
        pop     ecx
        inc     edx
        cmp     edx, [cur_width]
        ja      .ret
        mov     ah, [keybar_bgr_color]
        stosw
        inc     ecx
        jmp     .l
.ret_pop:
        pop     ecx
.ret:
        cmp     byte [edi-2], ' '
        jnz     @f
        dec     edi
        dec     edi
@@:
        push    edi
        mov     eax, [cur_width]
        mov     edx, [cur_height]
        call    get_console_ptr
        mov     ecx, edi
        pop     edi
        sub     ecx, edi
        shr     ecx, 1
        mov     al, ' '
        mov     ah, [keybar_name_color]
        rep     stosw
.done:
        popad
        ret

draw_cmdbar:
        mov     esi, [active_panel]
        add     esi, panel1_dir - panel1_data
        xor     eax, eax
        mov     edx, [cur_height]
        dec     edx
        dec     edx
        call    get_console_ptr
        mov     ah, [cmdbar_prefix_color]
        mov     ecx, [cur_width]
        dec     ecx
@@:
        lodsb
        test    al, al
        jz      @f
        stosw
        loop    @b
@@:
        mov     al, '>'
        stosw
        mov     al, ' '
        mov     ah, [cmdbar_normal_color]
        rep     stosw
        ret

draw_border:
        push    edi
        mov     al, 0xC9
        stosw
        mov     al, 0xCD
        lea     ecx, [ebx-2]
        rep     stosw
        mov     al, 0xBB
        stosw
        pop     edi
        add     edi, [cur_width]
        add     edi, [cur_width]
        lea     ecx, [edx-2]
.l:
        push    edi
        mov     al, 0xBA
        stosw
        mov     al, 0x20
        push    ecx
        lea     ecx, [ebx-2]
        rep     stosw
        pop     ecx
        mov     al, 0xBA
        stosw
        pop     edi
        add     edi, [cur_width]
        add     edi, [cur_width]
        loop    .l
        mov     al, 0xC8
        stosw
        mov     al, 0xCD
        lea     ecx, [ebx-2]
        rep     stosw
        mov     al, 0xBC
        stosw
        ret

draw_panel:
        mov     eax, [ebp + panel1_left - panel1_data]
        mov     edx, [ebp + panel1_top - panel1_data]
        call    get_console_ptr
; draw border
        mov     ah, [panel_border_color]
        mov     ebx, [ebp + panel1_width - panel1_data]
        mov     edx, [ebp + panel1_height - panel1_data]
        call    draw_border
        push    eax
        mov     eax, [ebp + panel1_left - panel1_data]
        mov     edx, [ebp + panel1_top - panel1_data]
        add     edx, [ebp + panel1_height - panel1_data]
        sub     edx, 3
        call    get_console_ptr
        pop     eax
        mov     al, 0xC7
        stosw
        mov     al, 0xC4
        lea     ecx, [ebx-2]
        rep     stosw
        mov     al, 0xB6
        stosw
        mov     eax, [ebp + panel1_width - panel1_data]
        sub     eax, 3
        shr     eax, 1
        mov     [column_width], eax
        mov     eax, [ebp + panel1_left - panel1_data]
        inc     eax
        mov     [column_left], eax
        add     eax, [column_width]
        mov     edx, [ebp + panel1_top - panel1_data]
        inc     edx
        mov     [column_top], edx
        dec     edx
        call    get_console_ptr
        mov     ah, [panel_border_color]
        mov     al, 0xD1
        mov     [edi], ax
        add     edi, [cur_width]
        add     edi, [cur_width]
        mov     ecx, [ebp + panel1_height - panel1_data]
        sub     ecx, 4
        mov     [column_height], ecx
        mov     al, 0xB3
@@:
        mov     [edi], ax
        add     edi, [cur_width]
        add     edi, [cur_width]
        loop    @b
        mov     al, 0xC1
        stosw
        mov     eax, [column_height]
        dec     eax
        mov     [ebp + panel1_colsz - panel1_data], eax
        add     eax, eax
        mov     [ebp + panel1_colst - panel1_data], eax
        mov     eax, [ebp + panel1_start - panel1_data]
        mov     [column_index], eax
        call    draw_column
        mov     eax, [ebp + panel1_width - panel1_data]
        sub     eax, 3
        mov     ecx, [column_width]
        sub     eax, ecx
        mov     [column_width], eax
        inc     ecx
        add     [column_left], ecx
        call    draw_column
; Заголовок панели (текущая папка)
        lea     esi, [ebp + panel1_dir - panel1_data]
        mov     edi, cur_header
        mov     ecx, [ebp + panel1_width - panel1_data]
        sub     ecx, 7
        movsb
@@:
        lodsb
        stosb
        dec     ecx
        test    al, al
        jz      .header_created
        cmp     al, '/'
        jnz     @b
        mov     edx, esi
@@:
        lodsb
        test    al, al
        jnz     @b
        sub     esi, edx
        dec     esi
        cmp     esi, ecx
        jbe     @f
        mov     word [edi], '..'
        mov     byte [edi+2], '.'
        add     edi, 3
        sub     ecx, 3
        add     edx, esi
        sub     edx, ecx
@@:
        mov     esi, edx
@@:
        lodsb
        stosb
        dec     ecx
        test    al, al
        jnz     @b
.header_created:
        mov     edx, [ebp + panel1_top - panel1_data]
        mov     eax, [ebp + panel1_left - panel1_data]
        shr     ecx, 1
        lea     eax, [eax+ecx+3]
        call    get_console_ptr
        mov     ah, [panel_active_header_color]
        cmp     ebp, [active_panel]
        jz      @f
        mov     ah, [panel_header_color]
@@:
        mov     al, ' '
        stosw
        mov     esi, cur_header
@@:
        lodsb
        test    al, al
        jz      @f
        stosw
        jmp     @b
@@:
        mov     al, ' '
        stosw
        mov     edx, [ebp + panel1_top - panel1_data]
        inc     edx
        mov     eax, [ebp + panel1_left - panel1_data]
        inc     eax
        call    get_console_ptr
        movzx   eax, [ebp + panel1_sortmode - panel1_data]
        mov     al, [compare_names+eax]
        stosb
        cmp     [ebp + panel1_numfiles - panel1_data], 0
        jz      .skip_curinfo
; Информация о выбранном файле
        mov     ebx, [ebp + panel1_index - panel1_data]
        mov     eax, [ebp + panel1_files - panel1_data]
        mov     ebx, [eax+ebx*4]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     ebx, [ebx+eax*4+32]
        add     ebx, [ebp + panel1_files - panel1_data]
        mov     eax, [ebp + panel1_left - panel1_data]
        add     eax, [ebp + panel1_width - panel1_data]
        dec     eax
        mov     edx, [ebp + panel1_top - panel1_data]
        add     edx, [ebp + panel1_height - panel1_data]
        dec     edx
        dec     edx
        call    get_console_ptr
        mov     ecx, [ebp + panel1_width - panel1_data]
        dec     ecx
        dec     ecx
; Время модификации
        sub     edi, 5*2
        sub     ecx, 6
        mov     al, [ebx+24+2]
        aam
        or      ax, 0x3030
        mov     [edi], ah
        mov     [edi+2], al
        mov     [edi+4], byte ':'
        mov     al, [ebx+24+1]
        aam
        or      ax, 0x3030
        mov     [edi+6], ah
        mov     [edi+8], al
        mov     al, [panel_normal_color]
        mov     [edi+1], al
        mov     [edi+3], al
        mov     [edi+5], al
        mov     [edi+7], al
        mov     [edi+9], al
        dec     edi
        mov     [edi], al
        dec     edi
        mov     byte [edi], ' '
; Дата модификации
        sub     edi, 8*2
        sub     ecx, 9
        mov     al, [ebx+28+0]
        aam
        or      ax, 0x3030
        mov     [edi], ah
        mov     [edi+2], al
        mov     [edi+4], byte '.'
        mov     al, [ebx+28+1]
        aam
        or      ax, 0x3030
        mov     [edi+6], ah
        mov     [edi+8], al
        mov     [edi+10], byte '.'
        mov     ax, [ebx+28+2]
        div     [_100]
        mov     al, ah
        aam
        or      ax, 0x3030
        mov     [edi+12], ah
        mov     [edi+14], al
        mov     al, [panel_normal_color]
        mov     [edi+1], al
        mov     [edi+3], al
        mov     [edi+5], al
        mov     [edi+7], al
        mov     [edi+9], al
        mov     [edi+11], al
        mov     [edi+13], al
        mov     [edi+15], al
        dec     edi
        mov     [edi], al
        dec     edi
        mov     [edi], byte ' '
; Размер
        std
        mov     ah, [panel_normal_color]
        dec     edi
        dec     edi
        dec     ecx
        test    byte [ebx], 0x10
        jz      .size_file
        push    ecx
        mov     esi, aFolder+aFolder.size-1
        mov     ecx, aFolder.size
        cmp     word [ebx+40], '..'
        jnz     @f
        cmp     byte [ebx+42], 0
        jnz     @f
        mov     esi, aUp+aUp.size-1
        mov     cl, aUp.size
@@:
        sub     [esp], ecx
@@:
        lodsb
        stosw
        loop    @b
        pop     ecx
        jmp     .size_done
.size_file:
        mov     edx, [ebx+36]
        test    edx, edx
        jz      .size_less_4g
        cmp     edx, 10*256
        jae     .size_tera
; в гигабайтах
        mov     al, 'G'
        jmp     .size_letter
.size_tera:
; в терабайтах
        shr     edx, 8
        mov     al, 'T'
        jmp     .size_letter
.size_less_4g:
        mov     edx, [ebx+32]
        cmp     edx, 10*(1 shl 20)
        jae     .size_mega
        cmp     edx, 1 shl 20
        jb      .size_num
        shr     edx, 10
        mov     al, 'K'
        jmp     .size_letter
.size_mega:
        mov     al, 'M'
        shr     edx, 20
.size_letter:
        stosw
        dec     ecx
        mov     al, ' '
        stosw
        dec     ecx
.size_num:
        xchg    eax, edx
        xor     edx, edx
        div     [_10d]
        xchg    eax, edx
        add     al, '0'
        mov     ah, [panel_normal_color]
        stosw
        dec     ecx
        test    edx, edx
        jnz     .size_num
.size_done:
        cld
; Имя
        sub     edi, ecx
        sub     edi, ecx
        lea     esi, [ebx+40]
@@:
        lodsb
        test    al, al
        jnz     @b
        sub     esi, ebx
        sub     esi, 41
        mov     ah, [panel_normal_color]
        cmp     esi, ecx
        lea     edx, [ebx+40]
        jbe     @f
        mov     al, '{'
        mov     [edi-2], ax
        add     edx, esi
        sub     edx, ecx
@@:
        mov     esi, edx
@@:
        lodsb
        test    al, al
        jz      @f
        stosw
        loop    @b
@@:
        mov     al, ' '
        rep     stosw
.skip_curinfo:
        call    draw_image
        ret

draw_column:
        mov     eax, [column_left]
        mov     edx, [column_top]
        call    get_console_ptr
; заголовок столбца
        push    edi
        mov     ah, [column_header_color]
        mov     al, ' '
        mov     ecx, [column_width]
if lang eq ru
        sub     ecx, 3
else
        sub     ecx, 4
end if
        shr     ecx, 1
        rep     stosw
if lang eq ru
        mov     al, 'И'
        stosw
        mov     al, 'м'
        stosw
        mov     al, 'я'
        stosw
else
        mov     al, 'N'
        stosw
        mov     al, 'a'
        stosw
        mov     al, 'm'
        stosw
        mov     al, 'e'
        stosw
end if
        mov     al, ' '
        mov     ecx, [column_width]
if lang eq ru
        sub     ecx, 2
else
        sub     ecx, 3
end if
        shr     ecx, 1
        rep     stosw
        pop     edi
        add     edi, [cur_width]
        add     edi, [cur_width]
; файлы
        mov     edx, [ebp + panel1_numfiles - panel1_data]
        mov     ecx, [column_height]
        dec     ecx
.l:
        cmp     [column_index], edx
        jae     .ret
        push    ecx
        mov     esi, [column_index]
        mov     ecx, [ebp + panel1_files - panel1_data]
        mov     esi, [ecx+esi*4]
        mov     ecx, [ebp + panel1_nfa - panel1_data]
        lea     esi, [esi + ecx*4 + 32 + 40]
        add     esi, [ebp + panel1_files - panel1_data]
; подсветка
;        call    insert_last_dot
        xor     ecx, ecx
.highlight_test_loop:
        mov     ebx, [highlight_groups+ecx*4]
        mov     al, [ebx + highlight.IncludeAttributes]
        mov     ah, [esi - 40]
        and     ah, al
        cmp     ah, al
        jnz     .highlight_test_failed
        push    edi
        lea     edi, [ebx + highlight.Mask]
        call    match_mask
        pop     edi
        jc      .highlight_test_failed
        mov     ah, [ebx + highlight.NormalColor]
        cmp     ebp, [active_panel]
        jnz     @f
        mov     ecx, [column_index]
        cmp     ecx, [ebp + panel1_index - panel1_data]
        jnz     @f
        mov     ah, [ebx + highlight.CursorColor]
@@:
        test    ah, ah
        jz      .nohighlight
        jmp     .doname
.highlight_test_failed:
        inc     ecx
        cmp     ecx, [highlight_num_groups]
        jb      .highlight_test_loop
.nohighlight:
        mov     ah, [panel_normal_color]
        cmp     ebp, [active_panel]
        jnz     @f
        mov     ecx, [column_index]
        cmp     ecx, [ebp + panel1_index - panel1_data]
        jnz     @f
        mov     ah, [panel_cursor_color]
@@:
.doname:
;        call    delete_last_dot
        mov     ecx, [column_width]
        push    edi
@@:
        lodsb
        test    al, al
        jz      @f
        stosw
        loop    @b
        cmp     byte [esi], 0
        jz      @f
        mov     byte [edi], '}'
@@:
        mov     al, ' '
        rep     stosw
        pop     edi
        add     edi, [cur_width]
        add     edi, [cur_width]
        inc     [column_index]
        pop     ecx
        dec     ecx
        jnz     .l
.ret:
        cmp     ebp, panel1_data
        jnz     .ret2
; Число экранов
        mov     eax, [num_screens]
        dec     eax
        jz      .ret2
        push    eax
        xor     eax, eax
        xor     edx, edx
        call    get_console_ptr
        mov     ah, [panel_nscreens_color]
        mov     al, '['
        stosw
        pop     eax
        push    -'0'
@@:
        xor     edx, edx
        div     [_10d]
        push    edx
        test    eax, eax
        jnz     @b
@@:
        pop     eax
        add     eax, '0'
        jz      @f
        mov     ah, [panel_nscreens_color]
        stosw
        jmp     @b
@@:
        mov     al, ']'
        mov     ah, [panel_nscreens_color]
        stosw
.ret2:
        ret

;insert_last_dot:
;        push    eax esi
;        mov     ah, 0
;.loop:
;        lodsb
;        test    al, al
;        jz      .done
;        cmp     al, '.'
;        jnz     .loop
;        mov     ah, 1
;        jmp     .loop
;.done:
;        test    ah, ah
;        jnz     @f
;        mov     byte [esi-1], '.'
;        mov     byte [esi], 0
;@@:
;        pop     esi eax
;        ret

;delete_last_dot:
;        push    esi
;@@:
;        cmp     byte [esi], 0
;        jz      @f
;        inc     esi
;        jmp     @b
;@@:
;        cmp     byte [esi-1], '.'
;        jnz     @f
;        mov     byte [esi-1], 0
;@@:     pop     esi
;        ret

read_folder:
        mov     eax, [ebp + panel1_nfa - panel1_data]
        mov     [dirinfo.size], eax
        shl     eax, 2
        add     eax, [ebp + panel1_files - panel1_data]
        mov     [dirinfo.dirdata], eax
        lea     eax, [ebp + panel1_dir - panel1_data]
        mov     [dirinfo.name], eax
        push    70
        pop     eax
        mov     ebx, dirinfo
        int     40h
        test    eax, eax
        jz      .ok
        cmp     eax, 6
        jz      .ok
; TODO: add error handling
        mov     [ebp + panel1_numfiles - panel1_data], 2
        mov     eax, [ebp + panel1_nfa - panel1_data]
        shl     eax, 2
        add     eax, [ebp + panel1_files - panel1_data]
        add     eax, 32+40
        mov     word [eax], '..'
        mov     byte [eax+2], 0
        add     eax, 304
        mov     dword [eax], 'Read'
        mov     dword [eax+4], ' err'
        mov     dword [eax+8], 'or'
        mov     eax, [ebp + panel1_files - panel1_data]
        mov     dword [eax], 0
        mov     dword [eax+4], 304
        and     dword [ebp + panel1_index - panel1_data], 0
        and     dword [ebp + panel1_start - panel1_data], 0
        ret
.ok:
        mov     eax, [dirinfo.dirdata]
        cmp     [eax+8], ebx
        jz      .readdone
        push    eax
        mov     eax, [ebp + panel1_files - panel1_data]
        cmp     eax, buf1
        jz      @f
        cmp     eax, buf2
        jz      @f
        call    mf_free
@@:
        pop     eax
        mov     eax, [eax+8]
        add     eax, 0xF
        and     eax, not 0xF
        push    eax
        imul    eax, 4+304
        add     eax, 32
        call    mf_alloc
        test    eax, eax
        jnz     .succ1
        pop     eax
; TODO: add error handling
        jmp     .readdone
.succ1:
        mov     [ebp + panel1_files - panel1_data], eax
        pop     [ebp + panel1_nfa - panel1_data]
        jmp     read_folder
.readdone:
        and     [ebp + panel1_start - panel1_data], 0
        and     [ebp + panel1_index - panel1_data], 0
        and     [ebp + panel1_start - panel1_data], 0
        mov     edi, [ebp + panel1_files - panel1_data]
        mov     eax, [ebp + panel1_nfa - panel1_data]
        lea     esi, [edi + eax*4 + 32]
        xor     eax, eax
        mov     ecx, [esi-32+4]
        jecxz   .loopdone
; Игнорируем специальные входы, соответствующие папке '.' и метке тома
.ptrinit:
        cmp     word [esi+eax+40], '.'
        jz      .loopcont
        test    byte [esi+eax], 8
        jnz     .loopcont
        stosd
.loopcont:
        add     eax, 304
        loop    .ptrinit
.loopdone:
        sub     edi, [ebp + panel1_files - panel1_data]
        shr     edi, 2
        mov     [ebp + panel1_numfiles - panel1_data], edi
.done:
; Сортировка
sort_files:
        movzx   eax, [ebp + panel1_sortmode - panel1_data]
        mov     ebx, [compare_fns + eax*4]
        mov     edx, [ebp + panel1_files - panel1_data]
        mov     ecx, [ebp + panel1_numfiles - panel1_data]
        call    sort
        ret

compare_name:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        add     esi, 40
        add     edi, 40
        jmp     strcmpi
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_name_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        add     esi, 40
        add     edi, 40
        xchg    esi, edi
        jmp     strcmpi
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

strcmpi:
        push    eax
@@:
        lodsb
        call    match_symbol
        jnz     .ret
        inc     edi
        test    al, al
        jnz     @b
.ret:
        pop     eax
        ret

compare_ext:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        add     esi, 40
        add     edi, 40
        push    esi edi
        call    seek_ext
        xchg    esi, edi
        call    seek_ext
        xchg    esi, edi
        call    strcmpi
        jnz     .ret
        pop     edi esi
        jmp     strcmpi
.ret:
        pop     edi esi
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_ext_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        add     esi, 40
        add     edi, 40
        push    esi edi
        call    seek_ext
        xchg    esi, edi
        call    seek_ext
        call    strcmpi
        jnz     .ret
        pop     edi esi
        xchg    esi, edi
        jmp     strcmpi
.ret:
        pop     edi esi
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

seek_ext:
        push    eax
        xor     eax, eax
.l:
        inc     esi
        cmp     byte [esi-1], '.'
        jnz     @f
        mov     eax, esi
@@:
        cmp     byte [esi-1], 0
        jnz     .l
        test    eax, eax
        jnz     @f
        lea     eax, [esi-1]
@@:
        mov     esi, eax
        pop     eax
        ret

compare_modified:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    edi
        mov     edi, [edi+28]
        cmp     edi, [esi+28]
        pop     edi
        jnz     @f
        push    edi
        mov     edi, [edi+24]
        cmp     edi, [esi+24]
        pop     edi
        jnz     @f
        add     esi, 40
        add     edi, 40
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_modified_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    esi
        mov     esi, [esi+28]
        cmp     esi, [edi+28]
        pop     esi
        jnz     @f
        push    esi
        mov     esi, [esi+24]
        cmp     esi, [edi+24]
        pop     esi
        jnz     @f
        add     esi, 40
        add     edi, 40
        xchg    esi, edi
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_size:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    edi
        mov     edi, [edi+36]
        cmp     edi, [esi+36]
        pop     edi
        jnz     @f
        push    edi
        mov     edi, [edi+32]
        cmp     edi, [esi+32]
        pop     edi
        jnz     @f
        add     esi, 40
        add     edi, 40
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_size_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    esi
        mov     esi, [esi+36]
        cmp     esi, [edi+36]
        pop     esi
        jnz     @f
        push    esi
        mov     esi, [esi+32]
        cmp     esi, [edi+32]
        pop     esi
        jnz     @f
        add     esi, 40
        add     edi, 40
        xchg    esi, edi
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_unordered:
        cmp     esi, edi
        ret
compare_unordered_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        cmp     edi, esi
        ret
.greater:
        test    esi, esi
        ret
.less:
        xor     edi, edi
        stc
        ret

compare_created:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    edi
        mov     edi, [edi+12]
        cmp     edi, [esi+12]
        pop     edi
        jnz     @f
        push    edi
        mov     edi, [edi+8]
        cmp     edi, [esi+8]
        pop     edi
        jnz     @f
        add     esi, 40
        add     edi, 40
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_created_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    esi
        mov     esi, [esi+12]
        cmp     esi, [edi+12]
        pop     esi
        jnz     @f
        push    esi
        mov     esi, [esi+8]
        cmp     esi, [edi+8]
        pop     esi
        jnz     @f
        add     esi, 40
        add     edi, 40
        xchg    esi, edi
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_accessed:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    edi
        mov     edi, [edi+20]
        cmp     edi, [esi+20]
        pop     edi
        jnz     @f
        push    edi
        mov     edi, [edi+16]
        cmp     edi, [esi+16]
        pop     edi
        jnz     @f
        add     esi, 40
        add     edi, 40
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

compare_accessed_rev:
        push    eax
        mov     eax, [ebp + panel1_nfa - panel1_data]
        add     esi, [ebp + panel1_files - panel1_data]
        add     edi, [ebp + panel1_files - panel1_data]
        lea     esi, [esi+eax*4+0x20]
        lea     edi, [edi+eax*4+0x20]
        pop     eax
        cmp     word [esi+40], '..'
        jnz     @f
        cmp     byte [esi+42], 0
        jz      .less
@@:     cmp     word [edi+40], '..'
        jnz     @f
        cmp     byte [edi+42], 0
        jz      .greater
@@:
        test    byte [esi], 10h
        jnz     .1dir
        test    byte [edi], 10h
        jnz     .greater
.eq1:
        push    esi
        mov     esi, [esi+20]
        cmp     esi, [edi+20]
        pop     esi
        jnz     @f
        push    esi
        mov     esi, [esi+16]
        cmp     esi, [edi+16]
        pop     esi
        jnz     @f
        add     esi, 40
        add     edi, 40
        xchg    esi, edi
        jmp     strcmpi
@@:
        ret
.greater:
        test    esi, esi
        ret
.1dir:
        test    byte [edi], 10h
        jnz     .eq1
.less:
        xor     edi, edi
        stc
        ret

match_mask:
; in: esi->name, edi->mask
; out: CF clear <=> match
        pusha
        xchg    esi, edi
.main_cycle:
        push    esi
@@:
        lodsb
        test    al, al
        jz      @f
        cmp     al, ','
        jz      @f
        cmp     al, '|'
        jnz     @b
@@:
        mov     [esi-1], byte 0
        xchg    esi, [esp]
        call    match_single_mask
        pop     esi
        mov     [esi-1], al
        jnc     .found
        cmp     al, ','
        jz      .main_cycle
.done_fail:
        stc
        popa
        ret
.found:
        test    al, al
        jz      .done_succ
        cmp     al, '|'
        jz      .test_exclude
        lodsb
        jmp     .found
.done_succ:
        clc
        popa
        ret
.test_exclude:
        push    esi
@@:
        lodsb
        test    al, al
        jz      @f
        cmp     al, ','
        jnz     @b
@@:
        mov     byte [esi-1], 0
        xchg    esi, [esp]
        call    match_single_mask
        pop     esi
        mov     [esi-1], al
        jnc     .done_fail
        test    al, al
        jz      .done_succ
        jmp     .test_exclude

match_single_mask:
; in: esi->mask, edi->name
; out: CF clear <=> match
        pusha
.mask_symbol:
        lodsb
        test    al, al
        jz      .mask_done
        cmp     al, '*'
        jz      .asterisk
        cmp     al, '?'
        jz      .quest
        cmp     al, '['
        jz      .list
        call    match_symbol
        jnz     .done_fail
        inc     edi
        jmp     .mask_symbol
.done_fail:
        stc
        popa
        ret
.mask_done:
        scasb
        jnz     .done_fail
.done_succ:
        clc
        popa
        ret
.quest:
        mov     al, 0
        scasb
        jz      .done_fail
        jmp     .mask_symbol
.list:
        lodsb
        cmp     al, ']'
        jz      .done_fail
        cmp     byte [esi+1], '-'
        jz      .range
        call    match_symbol
        jnz     .list
.listok:
        inc     edi
@@:
        lodsb
        cmp     al, ']'
        jnz     @b
        jmp     .mask_symbol
.range:
        call    match_symbol
        ja      @f
        mov     al, [esi+2]
        call    match_symbol
        jae     .listok
@@:
        inc     esi
        jmp     .list
.asterisk:
        push    edi
@@:
        call    match_single_mask
        jnc     @f
        mov     al, 0
        scasb
        jnz     @b
        pop     edi
        jmp     .done_fail
@@:
        pop     edi
        jmp     .done_succ

tolower:
        cmp     al, 'A'
        jb      @f
        cmp     al, 'Z'
        ja      @f
        add     al, ' '
@@:     ret

match_symbol:
; in: al,[edi]=symbols
; out: flags as 'cmp al,[edi]'
        push    eax
        call    tolower
        mov     ah, [edi]
        xchg    al, ah
        call    tolower
        cmp     ah, al
        pop     eax
        ret


header  db      'Kolibri Far 0.13'
;.length = $ - header
        db      0

nomem_draw      db      'No memory for redraw.',0
.size = $ - nomem_draw

def_left_dir    db      '/rd/1',0
def_right_dir   db      '/hd0/1',0

if lang eq ru
aFolder         db      'Папка'
.size = $-aFolder
aUp             db      'Вверх'
.size = $-aUp
aDrive          db      'Диск',0
aScreens        db      'Экраны',0
else
aFolder         db      'Folder'
.size = $-aFolder
aUp             db      'Up'
.size = $-aUp
aDrive          db      'Drive',0
aScreens        db      'Screens',0
end if

_10d dd 10
_100d dd 100
_10 db 10
_100 db 100

fpu_cw  dw      000011100111111b

keybar_panels:
if lang eq ru
; без клавиш-модификаторов
        db      'Помощь'
        db      'ПользМ'
        db      'Просм '
        db      'Редакт'
        db      'Копир '
        db      'Перен '
        db      'Папка '
        db      'Удален'
        db      'КонфМн'
        db      'Выход '
        db      'Модули'
        db      'Экраны'
; Shift
        db      'Добавл'
        db      'Распак'
        db      'АрхКом'
        db      'Редак.'
        db      'Копир '
        db      'Переим'
        db      '      '
        db      'Удален'
        db      'Сохран'
        db      'Послдн'
        db      'Группы'
        db      'Выбран'
; Ctrl
        db      'Левая '
        db      'Правая'
        db      'Имя   '
        db      'Расшир'
        db      'Модиф '
        db      'Размер'
        db      'Несорт'
        db      'Создан'
        db      'Доступ'
        db      'Описан'
        db      'Владел'
        db      'Сорт  '
; Ctrl+Shift
        db      '      '
        db      '      '
        db      'Просм '
        db      'Редакт'
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Alt
        db      'Левая '
        db      'Правая'
        db      'Смотр.'
        db      'Редак.'
        db      'Печать'
        db      'Связь '
        db      'Искать'
        db      'Истор '
        db      'Видео '
        db      'Дерево'
        db      'ИстПр '
        db      'ИстПап'
; Alt+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'КонфПл'
        db      '      '
        db      '      '
        db      '      '
; Alt+Ctrl
times 12 db     '      '
; Alt+Ctrl+Shift
times 12 db     '      '
else
; No modificators
        db      'Help  '
        db      'UserMn'
        db      'View  '
        db      'Edit  '
        db      'Copy  '
        db      'RenMov'
        db      'MkFold'
        db      'Delete'
        db      'ConfMn'
        db      'Quit  '
        db      'Plugin'
        db      'Screen'
; Shift
        db      'Add   '
        db      'Extrct'
        db      'ArcCmd'
        db      'Edit..'
        db      'Copy  '
        db      'Rename'
        db      '      '
        db      'Delete'
        db      'Save  '
        db      'Last  '
        db      'Group '
        db      'SelUp '
; Ctrl
        db      'Left  '
        db      'Right '
        db      'Name  '
        db      'Extens'
        db      'Modifn'
        db      'Size  '
        db      'Unsort'
        db      'Creatn'
        db      'Access'
        db      'Descr '
        db      'Owner '
        db      'Sort  '
; Ctrl+Shift
        db      '      '
        db      '      '
        db      'View  '
        db      'Edit  '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Alt
        db      'Left  '
        db      'Right '
        db      'View..'
        db      'Edit..'
        db      'Print '
        db      'MkLink'
        db      'Find  '
        db      'Histry'
        db      'Video '
        db      'Tree  '
        db      'ViewHs'
        db      'FoldHs'
; Alt+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'ConfPl'
        db      '      '
        db      '      '
        db      '      '
; Alt+Ctrl
times 12 db     '      '
; Alt+Ctrl+Shift
times 12 db     '      '
end if

keybar_viewer:
if lang eq ru
; без клавиш-модификаторов
        db      'Помощь'
        db      'Развер'
        db      'Выход '
        db      'Код   '
        db      '      '
        db      'Редакт'
        db      'Поиск '
keybar_cp:
        db      'cp1251'
        db      '      '
        db      'Выход '
        db      'Модули'
        db      'Экраны'
; Shift
        db      '      '
        db      'Слова '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Дальше'
        db      'Таблиц'
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Ctrl
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Позиц '
        db      '      '
        db      '      '
; Ctrl+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Alt
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Печать'
        db      '      '
        db      'Назад '
        db      'Перейт'
        db      'Видео '
        db      '      '
        db      'ИстПр '
        db      '      '
; Alt+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Конфиг'
        db      '      '
        db      '      '
        db      '      '
; Alt+Ctrl
times 12 db     '      '
; Alt+Ctrl+Shift
times 12 db     '      '
else
; No modificators
        db      'Help  '
        db      'Unwrap'
        db      'Quit  '
        db      'Hex   '
        db      '      '
        db      'Edit  '
        db      'Search'
keybar_cp:
        db      'cp1251'
        db      '      '
        db      'Quit  '
        db      'Plugin'
        db      'Screen'
; Shift
        db      '      '
        db      'WWrap '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Next  '
        db      'Table '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Ctrl
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'GoFile'
        db      '      '
        db      '      '
; Ctrl+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
; Alt
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Print '
        db      '      '
        db      'Prev  '
        db      'Goto  '
        db      'Video '
        db      '      '
        db      'ViewHs'
        db      '      '
; Alt+Shift
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      '      '
        db      'Config'
        db      '      '
        db      '      '
        db      '      '
; Alt+Ctrl
times 12 db     '      '
; Alt+Ctrl+Shift
times 12 db     '      '
end if

        align   4
cur_width       dd      80
cur_height      dd      25
max_width = 256
max_height = 256

active_panel    dd      panel1_data

console_colors  dd      0x000000, 0x000080, 0x008000, 0x008080
                dd      0x800000, 0x800080, 0x808000, 0xC0C0C0
                dd      0x808080, 0x0000FF, 0x00FF00, 0x00FFFF
                dd      0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF

compare_fns     dd      compare_name
                dd      compare_name_rev
                dd      compare_ext
                dd      compare_ext_rev
                dd      compare_modified
                dd      compare_modified_rev
                dd      compare_size
                dd      compare_size_rev
                dd      compare_unordered
                dd      compare_unordered_rev
                dd      compare_created
                dd      compare_created_rev
                dd      compare_accessed
                dd      compare_accessed_rev

ctrlkey_tests   dd      ctrlkey_test0
                dd      ctrlkey_test1
                dd      ctrlkey_test2
                dd      ctrlkey_test3
                dd      ctrlkey_test4
ctrlkey_tests_num = 5

virtual at 0
screen_vtable:
        .OnRedraw       dd      ?
        .OnKey          dd      ?
        .keybar         dd      ?
        .getname        dd      ?
end virtual

panels_vtable:
        dd      panels_OnRedraw
        dd      panels_OnKey
        dd      keybar_panels
        dd      panels_getname

viewer_vtable:
        dd      viewer_OnRedraw
        dd      viewer_OnKey
        dd      keybar_viewer
        dd      viewer_getname

encodings:
.cp866 = 0
.cp1251 = 1

.names:
        db      'cp866   '
        db      'cp1251  '

.tables:
; cp866 - trivial map
        times 128 db %+127
; cp1251
        db      0x3F,0x3F,0x27,0x3F,0x22,0x3A,0xC5,0xD8,0x3F,0x25,0x3F,0x3C,0x3F,0x3F,0x3F,0x3F
        db      0x3F,0x27,0x27,0x22,0x22,0x07,0x2D,0x2D,0x3F,0x54,0x3F,0x3E,0x3F,0x3F,0x3F,0x3F
        db      0xFF,0xF6,0xF7,0x3F,0xFD,0x3F,0xB3,0x15,0xF0,0x63,0xF2,0x3C,0xBF,0x2D,0x52,0xF4
        db      0xF8,0x2B,0x49,0x69,0x3F,0xE7,0x14,0xFA,0xF1,0xFC,0xF3,0x3E,0x3F,0x3F,0x3F,0xF5
        times 0x30 db %-1+0x80
        times 0x10 db %-1+0xE0

active_screen   dd      0
tabsize         dd      8

ascii2scan:
        times 32 db 0
        db      0x39,0x02,0x03,0x04,0x05,0x06,0x08,0x28,0x0A,0x0B,0x09,0x0D,0x33,0x0C,0x34,0x35
        db      0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x27,0x27,0x33,0x0D,0x34,0x35
        db      0x03,0x1E,0x30,0x2E,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18
        db      0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11,0x2D,0x15,0x2C,0x1A,0x2B,0x1B,0x07,0x0C
        db      0x29,0x1E,0x30,0x2E,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18
        db      0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11,0x2D,0x15,0x2C,0x1A,0x2B,0x1B,0x29,0x00
        db      0x21,0x33,0x20,0x16,0x26,0x14,0x27,0x19,0x30,0x10,0x13,0x25,0x2F,0x15,0x24,0x22
        db      0x23,0x2E,0x31,0x12,0x1E,0x1A,0x11,0x2D,0x17,0x18,0x1B,0x1F,0x32,0x28,0x34,0x2C
        db      0x21,0x33,0x20,0x16,0x26,0x14,0x27,0x19,0x30,0x10,0x13,0x25,0x2F,0x15,0x24,0x22
        times 48 db 0
        db      0x23,0x2E,0x31,0x12,0x1E,0x1A,0x11,0x2D,0x17,0x18,0x1B,0x1F,0x32,0x28,0x34,0x2C
        db      0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

; Клавишные сочетания
; db scancode, reserved
; dw ctrlstate
; dd handler
; ctrlstate: младшие 4 бита - для Shift, следующие - для Ctrl, следующие - для Alt
; 0 = ни одна клавиша не нажата
; 1 = ровно одна нажата
; 2 = обе нажаты
; 3 = левая нажата, правая нет
; 4 = правая нажата, левая нет
panels_ctrlkeys:
        dw      0x48, 0
        dd      panels_OnKey.up
        dw      0x50, 0
        dd      panels_OnKey.down
        dw      0x4B, 0
        dd      panels_OnKey.left
        dw      0x4D, 0
        dd      panels_OnKey.right
        dw      0xF, 0
        dd      panels_OnKey.tab
        dw      0x47, 0
        dd      panels_OnKey.home
        dw      0x4F, 0
        dd      panels_OnKey.end
        dw      0x1C, 0
        dd      panels_OnKey.enter
        dw      0x3D, 0
        dd      panels_OnKey.f3
        dw      0x42, 0
        dd      panels_OnKey.f8
        dw      0x44, 0
        dd      exit
repeat 9-3+1
        dw      0x3D+%-1, 0x10
        dd      panels_OnKey.ctrl_f39
end repeat
        dw      0x3B, 0x100
        dd      panels_OnKey.alt_f12
        dw      0x3C, 0x100
        dd      panels_OnKey.alt_f12
        dw      0x58, 0
        dd      F12
        dw      0x13, 0x10
        dd      panels_OnKey.ctrl_r
        db      0

viewer_ctrlkeys:
        dw      1, 0
        dd      viewer_OnKey.exit
        dw      0x51, 0
        dd      viewer_OnKey.pgdn
        dw      0x49, 0
        dd      viewer_OnKey.pgup
        dw      0x50, 0
        dd      viewer_OnKey.down
        dw      0x48, 0
        dd      viewer_OnKey.up
        dw      0x4B, 0
        dd      viewer_OnKey.left
        dw      0x4B, 0x10
        dd      viewer_OnKey.ctrl_left
        dw      0x4B, 0x11
        dd      viewer_OnKey.ctrl_shift_left
        dw      0x4C, 0
        dd      viewer_OnKey.exit
        dw      0x4D, 0
        dd      viewer_OnKey.right
        dw      0x4D, 0x10
        dd      viewer_OnKey.ctrl_right
        dw      0x4D, 0x11
        dd      viewer_OnKey.ctrl_shift_right
        dw      0x3C, 0
        dd      viewer_OnKey.f2
        dw      0x3D, 0
        dd      viewer_OnKey.exit
        dw      0x3E, 0
        dd      viewer_OnKey.f4
        dw      0x42, 0
        dd      viewer_OnKey.f8
        dw      0x44, 0
        dd      viewer_OnKey.exit
        dw      0x47, 0
        dd      viewer_OnKey.home
        dw      0x4F, 0
        dd      viewer_OnKey.end
        dw      0x58, 0
        dd      F12
        db      0

dirinfo:
                dd      1
.first          dd      0
                dd      0
.size           dd      300
.dirdata        dd      0
                db      0
.name           dd      0

readinfo:
                dd      0
.first          dq      0
.size           dd      0
.data           dd      0
                db      0
.name           dd      0

attrinfo:
                dd      5
                dd      0
                dd      0
                dd      0
                dd      .attr
                db      0
.name           dd      0

delinfo:
                dd      8
                dd      0
                dd      0
                dd      0
                dd      0
                db      0
                dd      execdata

if lang eq ru
compare_names   db      'иИрРмМаАнНсСдД'
else
compare_names   db      'nNxXmMsSuUcCaA'
end if

; Панель
panel_normal_color      db      1Bh
panel_border_color      db      1Bh
panel_cursor_color      db      30h
panel_header_color      db      1Bh
panel_active_header_color db    30h
column_header_color     db      1Eh
panel_nscreens_color    db      0Bh
; Меню
menu_normal_color       db      3Fh
menu_selected_color     db      0Fh
menu_highlight_color    db      3Eh
menu_selected_highlight_color db 0Eh
menu_border_color       db      3Fh
menu_header_color       db      3Fh
menu_scrollbar_color    db      3Fh
; Линейка клавиш
keybar_number_color     db      7
keybar_name_color       db      30h
keybar_bgr_color        db      7
; Командная строка
cmdbar_normal_color     db      7
cmdbar_prefix_color     db      7
; Просмотрщик
view_normal_color       db      1Bh
view_status_color       db      30h
view_arrows_color       db      1Eh

; Подсветка файлов
highlight_num_groups    dd      10
highlight_groups        dd      highlight_group0
                dd      highlight_group1
                dd      highlight_group2
                dd      highlight_group3
                dd      highlight_group4
                dd      highlight_group5
                dd      highlight_group6
                dd      highlight_group7
                dd      highlight_group8
                dd      highlight_group9

; Формат описания группы подсветки:
virtual at 0
highlight:
        .NormalColor            db ?
        .CursorColor            db ?
        .IncludeAttributes      db ?
        .Mask:                  ; ASCIIZ-string
end virtual

highlight_group0:
        db      13h
        db      38h
        db      2
        db      '*',0
highlight_group1:
        db      13h
        db      38h
        db      4
        db      '*',0
highlight_group2:
        db      1Fh
        db      3Fh
        db      10h
        db      '*|..',0
highlight_group3:
        db      0
        db      0
        db      10h
        db      '..',0
highlight_group4:
        db      1Ah
        db      3Ah
        db      0
        db      '*.exe,*.com,*.bat,*.cmd',0
highlight_group5:
        db      1Ah
        db      3Ah
        db      0
        db      '*|*.*',0
highlight_group6:
        db      1Dh
        db      3Dh
        db      0
        db      '*.rar,*.zip,*.[zj],*.[bg7]z,*.[bg]zip,*.tar,*.t[ag]z,*.ar[cj],*.r[0-9][0-9],'
        db      '*.a[0-9][0-9],*.bz2,*.cab,*.msi,*.jar,*.lha,*.lzh,*.ha,*.ac[bei],*.pa[ck],'
        db      '*.rk,*.cpio,*.rpm,*.zoo,*.hqx,*.sit,*.ice,*.uc2,*.ain,*.imp,*.777,*.ufa,*.boa,'
        db      '*.bs[2a],*.sea,*.hpk,*.ddi,*.x2,*.rkv,*.[lw]sz,*.h[ay]p,*.lim,*.sqz,*.chz',0
highlight_group7:
        db      16h
        db      36h
        db      0
        db      '*.bak,*.tmp',0
highlight_group8:
        db      17h
        db      37h
        db      0
        db      '*.asm,*.inc',0
highlight_group9:
        db      1Fh
        db      3Fh
        db      10h
        db      '*',0

bWasE0          db      0
ctrlstate       db      0
MemForImage     dd      0

associations:
        dd      aAsm, tinypad
        dd      aInc, tinypad
        dd      aTxt, tinypad
        dd      aJpg, jpegview
        dd      aJpeg, jpegview
        dd      aGif, gifview
        dd      aWav, ac97wav
        dd      aMp3, ac97wav
        dd      aMid, midamp
        dd      aBmp, mv
        dd      aPng, archer
        dd      aRtf, rtfread
associations_end:

aAsm db 'asm',0
aInc db 'inc',0
aTxt db 'txt',0
tinypad db '/rd/1/TinyPad',0

aJpg db 'jpg',0
aJpeg db 'jpeg',0
jpegview db '/rd/1/JpegView',0

aGif db 'gif',0
gifview db '/rd/1/GIFVIEW',0

aWav db 'wav',0
aMp3 db 'mp3',0
ac97wav db '/rd/1/AC97WAV',0

aMid db 'mid',0
midamp db '/rd/1/MIDAMP',0

aBmp db 'bmp',0
mv db '/rd/1/MV',0

aPng db 'png',0
archer db '/rd/1/@rcher',0

aRtf db 'rtf',0
rtfread db '/rd/1/RtfRead',0

execinfo:
        dd      7
        dd      0
execparams dd   0
        dd      0
        dd      0
        db      0
execptr dd      ?

IncludeIGlobals

i_end:

IncludeUGlobals

execdata rb     1024
        align   4
attrinfo.attr   rb      40

panel1_data:
panel1_left     dd      ?
panel1_top      dd      ?
panel1_width    dd      ?
panel1_height   dd      ?
panel1_index    dd      ?
panel1_start    dd      ?
panel1_colsz    dd      ?
panel1_colst    dd      ?
panel1_sortmode db      ?
                rb      3
panel1_nfa      dd      ?
panel1_numfiles dd      ?
panel1_files    dd      ?
panel1_dir      rb      1024

panel2_data:
panel2_left     dd      ?
panel2_top      dd      ?
panel2_width    dd      ?
panel2_height   dd      ?
panel2_index    dd      ?
panel2_start    dd      ?
panel2_colsz    dd      ?
panel2_colst    dd      ?
panel2_sortmode db      ?
                rb      3
panel2_nfa      dd      ?
panel2_numfiles dd      ?
panel2_files    dd      ?
panel2_dir      rb      1024

console_data    rb      max_width*max_height*2

cur_header      rb      max_width
tmp             dd      ?

skinh           dd      ?
std_colors      rd      10

column_left     dd      ?
column_top      dd      ?
column_width    dd      ?
column_height   dd      ?
column_index    dd      ?

scrpos          dq      ?
viewer_right_side dq    ?

saved_file_name:
procinfo        rb      1024

driveinfo       rb      32+304
tmpname         rb      32

screens         dd      ?
num_screens     dd      ?
active_screen_vtable dd ?
active_screen_data dd   ?

; stack
        align   512
        rb      512
stacktop:
; buffers for directory - may be resized dynamically
buf1    rb      4*304 + 32 + 304*304
buf2    rb      4*304 + 32 + 304*304

mem:
