include doszip/doszip.inc
include	stdlib.inc
include	io.inc
include	dos.inc
include	disk.inc
include	math.inc
include	malloc.inc
include	string.inc
include	conio.inc
include	mouse.inc
include	keyb.inc
include	progress.inc
ifdef __TE__
include	tinfo.inc
endif

	public	fblk_select
	public	fblk_invert
	public	pcell_show
	public	pcell_update
  ifdef __MOUSE__
	public	pcell_setxy
	public	pcell_move
  endif
	public	panel_state
	public	panel_stateab
	public	panel_open
	public	panel_open_ab
	public	panel_close
	public	panel_hide
	public	panel_show
	public	panel_setactive
	public	panel_curobj
	public	panel_findnext
	public	panel_setid
	public	panel_openmsg
	public	panel_putinfo
	public	panel_putmini
	public	panel_putitem
	public	panel_sethdd
	public	panel_read
	public	panel_reread
	public	panel_redraw
	public	panel_toggle
	public	panel_update
	public	redraw_panels
	public	panel_xormini
	public	panel_xorinfo
	public	panel_xycmd
	public	panel_event
	public	cpanel_state
	public	cpanel_findfirst
	public	cpanel_gettarget
	public	cpanel_setpath
	public	cpanel_deselect

	public	cp_copyselected

	extrn	errnomsg:DIST
	extrn	MOBJ_STATUSLINE:word

_DATA	SEGMENT

ifdef __ROT__
cp_rot		db 'home',0
;cp_doc		db '.edit',0
cp_drv		db 'X:',0
endif
cp_openmsg	db 'open:',0
cp_pinfo0	db ' %s ',0
cp_pinfo1	db ' %c:\...%s ',0
cp_emptydisk	db '[%c:] Empty disk',0
cp_bselected	db '%s byte in %d file(s)',0
cp_copyselected	db "%d file(s) to",0
ifdef __TEBLK__
TE_FFBLK	label	S_FFBLK
endif
DB_VIDISK  	db 0		; ff_reserved	DB 21 dup(?)
CP_VIDISK  	db 'C:\',0
CP_VIFREE  	db ' Free:',10
CP_VITOTAL 	db 'Total:',0
ifdef __TEBLK__
		dw ?
		db _A_SUBDIR or _A_SYSTEM
		dw ?		; ff_ftime	DW ?
		dw ?		; ff_fdate	DW ?
		dd ?		; ff_fsize	DD ?
		db '.edit',0	; ff_name	DB 13 dup(?)
endif
CP_VIBYTE  	db 'byte',0
CP_NONAME  	db 'NONAME',0
format_20s 	db '%20s',0
format_24s 	db '%24s',0
cp_error_chdir	db "Error open directory",0
cp_chdir_format	db "Can't open the directory:",10,"%s",10,10,"%s",0

_DATA	ENDS

_DZIP	SEGMENT

fblk_selectable proc
	xor ax,ax
	.if !(byte ptr es:[bx] & _A_VOLID)
	    inc ax
	    .if byte ptr es:[bx] & _A_SUBDIR
		.if !(cflag & _C_SELECTDIR)
		    dec ax
		.endif
	    .endif
	.endif
	or ax,ax
	ret
fblk_selectable endp

fblk_select proc pascal fblk:dword
	les bx,fblk
	call fblk_selectable
	.if !ZERO?
	    invoke fbselect,es::bx
	.endif
	ret
fblk_select endp

fblk_invert proc pascal fblk:dword
	les bx,fblk
	call fblk_selectable
	.if !ZERO?
	    invoke fbinvert,es::bx
	.endif
	ret
fblk_invert endp

pcell_select proc	; AX: panel
	push si
	mov si,ax
	call panel_curobj
	.if !ZERO?
	    invoke fblk_invert,dx::bx
	    .if ax
		mov ax,si
		call pcell_update
		mov ax,1
	    .endif
	.endif
	pop si
	ret
pcell_select endp

pcell_set proc
	push si
	push di
	mov si,ax
	mov di,word ptr [si].pn_xl
	mov al,[di].xl_cols
	mul [di].xl_rows
	mov dx,[si].pn_fcb_count
	sub dx,[si].pn_fcb_index
	.if ax >= dx
	    mov ax,dx
	.endif
	mov [si].pn_cel_count,ax
	mov dx,[si].pn_cel_index
	.if dx < ax
	    mov ax,dx
	.else
	    dec ax
	.endif
	mov [si].pn_cel_index,ax
	cwd
	div [di].xl_rows
	mov ah,0
	mov cx,ax
	mul [di].xl_rows
	mov bx,[si].pn_cel_index
	sub bx,ax
	mov al,[di].xl_cpos.rc_col
	inc ax
	mul cx
	mov cx,ax
	mov ax,[di+12]
	add al,cl
	add ah,bl
	mov [di+4],ax
	mov ax,[di+14]
	mov [di+6],ax
	mov ax,[si].pn_cel_index
	pop di
	pop si
	ret
pcell_set endp

pcell_open proc
	mov bx,ax
	mov al,at_background[B_DarkGray]
	or  al,at_foreground[F_Black]
	invoke dlopen,[bx].pn_xl,ax,0
	ret
pcell_open endp

pcell_show proc
	push si
	push di
	mov si,ax
	mov di,word ptr [si].pn_xl
	xor ax,ax
	.if !([di].xl_flag & _D_DOPEN or _D_ONSCR)
	    mov ax,si
	    call pcell_set
	    xor ax,ax
	    .if [si].pn_cel_count != ax
		mov ax,si
		call pcell_open
		invoke dlshow,ds::di
		mov ax,1
	    .endif
	.endif
	pop di
	pop si
	ret
pcell_show endp

pcell_update proc
	push si
	mov  si,ax
	invoke dlclose,[si].pn_xl
	.if ax
	    mov	 ax,si
	    call pcell_set
	    mov	 ax,si
	    call panel_curobj
	    push dx
	    push bx
	    xor	 ax,ax
	    mov	 bx,word ptr [si].pn_xl
	    mov	 al,[bx].xl_rect.rc_x
	    push ax
	    mov	 al,[bx].xl_rect.rc_y
	    push ax
	    call [si].pn_putfcb
	    mov	 ax,si
	    call pcell_open
	    invoke dlshow,[si].pn_xl
	    mov	 ax,si
	    call panel_putmini
	    mov	 ax,1
	.endif
	pop si
	ret
pcell_update endp

ifdef __MOUSE__

_XY_DRVINFO	= 8
_XY_CONFIG	= 7
_XY_MINISTATUS	= 6
_XY_NEWDISK	= 5
_XY_MOVEUP	= 4
_XY_MOVEDOWN	= 3
_XY_FILE	= 2
_XY_INSIDE	= 1
_XY_OUTSIDE	= 0

pcell_move proc	pascal uses si di ; AX = panel
local	fblk:dword
local	rect:dword
local	dialog:dword
local	mouse:word
local	dlflag:word
local	selected:word
	mov si,ax
	call cpanel_findfirst
	jz pcell_move_end
	stoso fblk,dx,bx
	mov di,word ptr [si].pn_xl
	movmx rect,[di].xl_rect
	mov ax,si
	call panel_selected
	mov selected,ax
	call mousep
	cmp ax,1
	jne pcell_move_end
	;
	; Create a movable object
	;
	mov mouse,ax
	les bx,keyshift
	.if byte ptr es:[bx] & 3
	    dec mouse
	.endif
	.if selected
	    mov rect.rc_col,15
	    jmp @F
	.endif
	mov ax,[si].pn_flag
	.if ax & _P_DETAIL
	    sub rect.rc_col,26
	.endif
	.while 1
	    mov bl,rect.rc_x
	    add bl,rect.rc_col
	    dec bl
	    mov bh,rect.rc_y
	    call @getxyw
	    .break .if al != ' '
	    dec rect.rc_col
	.endw
	inc rect.rc_col
      @@:
	inc rect.rc_col
	dec rect.rc_x
	xor ax,ax
	mov al,at_background[B_DarkGray]
	or  al,at_foreground[F_Black]
	invoke rcopen,rect,_D_DMOVE or _D_CLEAR or _D_COLOR,ax,0,0
	stom dialog
	add ax,2
	mov bx,ax
	mov cx,selected
	.if cx
	    push cx
	    xor	 cx,cx
	    mov	 ax,offset cp_copyselected
	    call @wcputf
	    pop  ax
	.else
	    mov	 cl,rect.rc_col
	    dec	 cl
	    lodm fblk
	    add	 ax,fb_name
	    call @wcputs
	.endif
	mov dlflag,_D_DMOVE or _D_CLEAR or _D_COLOR or _D_DOPEN
	invoke rcshow, rect, dlflag, dialog
	or dlflag,_D_ONSCR
	mov bx,word ptr rect
	scputw@ bl, bh, 1, ' '
	add bl,rect.rc_col
	dec bl
	mov ax,' '
	.if byte ptr mouse
	    mov al,'+'
	.endif
	scputw@ bl, bh, 1, ax
	;
	; Move the object
	;
	.while 1
	    call mousep
	    .break .if ax != 1
	    call mousex
	    .if al == rect.rc_x
		call mousey
		cmp al,rect.rc_y
		je @F
	    .endif
	    pushm rect
	    pushm dialog
	    push dlflag
	    call mousex
	    push ax
	    call mousey
	    push ax
	  ifndef __WCC__
	    call rcmove
	    stom rect
	  else
	    lea  ax,rect
	    push ax
	    call rcmove
	  endif
	 @@:
	    les bx,keyshift
	    mov dl,es:[bx]
	    xor ax,ax
	    .if ax != mouse
		.if !(dl & 3)
		    .continue
		.endif
		mov mouse,ax
		mov bx,word ptr rect
		add bl,rect.rc_col
		dec bl
		scputw@ bl, bh, 1, ' '
	    .else
		.if dl & 3
		    .continue
		.endif
		inc ax
		mov mouse,ax
		mov bx,word ptr rect
		add bl,rect.rc_col
		dec bl
		scputw@ bl, bh, 1, '+'
	    .endif
	.endw
	invoke rcclose, rect, dlflag, dialog
	;
	; Find out where the object is
	;
	push ds
	mov ax,[si].pn_flag
	mov dx,offset spanela
	.if !(ax & _P_PANELID)
	    add dx,SIZE S_PANEL
	.endif
	push dx
	call mousex
	push ax
	mov  si,ax
	call mousey
	push ax
	mov  di,ax
	call panel_xycmd
	.if ax
	    mov ax,1
	    .if !mouse
		inc ax
	    .endif
	.endif
	.if !ax
	    mov cx,9
	    mov bx,offset MOBJ_STATUSLINE
	    mov ax,si
	    mov dx,di
	    call STATUSLINE_XY
	    .if !ZERO?
		mov ax,cx
		dec ax
		.if ax == 6
		    mov ax,3
		.elseif ax > 6
		    jmp @F
		.elseif ax == 4
		    mov ax,1
		.elseif ax > 4
		    mov ax,4
		.elseif ax == 3
		    mov ax,2
		.elseif ax == 2
		    jmp @F
		.else
		    mov ax,5
		.endif
		jmp pcell_move_end
	    .endif
	  @@:
	    .if cflag & _C_COMMANDLINE
		les bx,DLG_Commandline
		mov al,es:[bx+5]
		mov ah,0
		.if ax == di
		    mov ax,6
		.else
		    xor ax,ax
		.endif
	    .else
		xor ax,ax
	    .endif
	.endif
    pcell_move_end:
	ret
pcell_move endp

endif

xcell_getrect proc pascal xcell:dword, index:word
	push	si
	push	di
	mov	cx,index
	les	bx,xcell
	mov	al,es:[bx].xl_rows
	mov	ah,0
	mov	di,ax
	mov	ax,cx
	cwd
	div	di
	mov	si,ax
	mul	di
	sub	cx,ax
	mov	al,es:[bx+14]
	mov	ah,0
	inc	ax
	mul	si
	add	ax,es:[bx+12]
	mov	dx,es:[bx+14]
	add	ah,cl
	pop	di
	pop	si
	ret
xcell_getrect endp

ifdef __MOUSE__

pcell_setxy proc pascal uses si di panel:word, xpos:word, ypos:word
local	rect:dword
	mov si,panel
	mov ax,si
	call panel_state
	.if ax
	    invoke panel_xycmd,si,xpos,ypos
	    .while ax != 2
		call mousep
		.if ax != 2
		    xor	ax,ax
		    jmp @F
		.endif
		call mousex
		mov di,ax
		call mousey
		mov si,ax
		invoke panel_xycmd,panel,di,si
		.if ax == _XY_FILE
		    invoke pcell_setxy,panel,di,si
		    jmp @F
		.endif
	    .endw
	    xor ax,ax
	    mov si,ax
	    mov di,ax
	    .while 1
		mov bx,panel
		mov ax,[bx].pn_cel_count
		.if di < ax
		    invoke xcell_getrect,[bx].pn_xl,di
		    stom rect
		    invoke rcxyrow,dx::ax,xpos,ypos
		    .if ZERO?
			inc di
		    .else
			inc si
			.break
		    .endif
		.endif
	    .endw
	    .if si == 1
		mov bx,panel
		mov ax,di
		.if ax != [bx].pn_cel_index
		    mov [bx].pn_cel_index,ax
		    mov ax,panel
		    call pcell_update
		.endif
	    .else
		.while 1
		    call mousep
		    .break .if ax != 2
		    push panel
		    call mousex
		    push ax
		    call mousey
		    push ax
		    call panel_xycmd
		    .break .if ax == _XY_FILE
		.endw
		.if ax == _XY_FILE
		    call mousex
		    mov si,ax
		    call mousey
		    invoke pcell_setxy, panel, si, ax
		.endif
		jmp @F
	    .endif
	    call mousep
	    .if ax != 2
		invoke mousewait, xpos, ypos, 1
		mov ax,panel
		call pcell_move
		.if ax == 1
		    call cmcopy
		.elseif ax == 2
		    call cmmove
		.elseif ax == 3
		    call cmview
		.elseif ax == 4
		    call cmedit
		.elseif ax == 5
		    call cmdelete
		.elseif ax == 6
		    call cmmklist
		.elseif !ax
		    mov di,10
		    .while di
			invoke delay, 16
			invoke mousep
			.break .if !ZERO?
			dec di
		    .endw
		    call mousep
		    .if !ZERO?
			call mousex
			.if ax == xpos
			    call mousey
			    .if ax == ypos
				invoke panel_event, panel, KEY_ENTER
			    .endif
			.endif
		    .endif
		    mov ax,1
		.endif
	    .else
		mov  ax,panel
		call pcell_select
		xor  ax,ax
		mov  al,rect.rc_x
		push ax
		mov  al,rect.rc_y
		push ax
		mov  al,rect.rc_col
		push ax
		call mousewait
		push panel
		call mousex
		push ax
		call mousey
		push ax
		call pcell_setxy
	    .endif
	.endif
      @@:
	ret
pcell_setxy endp

endif

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cpanel_state proc
	mov ax,cpanel
cpanel_state endp

panel_state proc
	mov dx,ax
	mov bx,ax
	xor ax,ax
	mov bx,word ptr [bx].pn_dialog
	.if word ptr [bx].dl_wp != ax
	    mov bx,dx
	    mov bx,word ptr [bx].pn_wsub
	    mov ax,word ptr [bx].ws_fcb
	    shr ax,2
	.endif
	ret
panel_state endp

panel_stateab proc
	mov ax,panela
	call panel_state
	.if !ZERO?
	    mov ax,panelb
	    call panel_state
	.endif
	ret
panel_stateab endp

panel_open proc pascal uses si di
local	path[WMAXPATH]:byte
local	wsub:dword
	mov si,ax
	mov di,[si]
	movmm wsub,[si].pn_wsub
	invoke wsopen,dx::ax
	.if ax
	    xor ax,ax
	    mov [si].pn_cel_count,ax
	    .if si == cpanel
		push [di]
		invoke strcpy,addr path,addr [di].wp_path
		mov [di].wp_path,0
		invoke cominit, wsub
		pop ax
	      ifdef __ARC__
		.if ax & _W_ARCHIVE
		    push ax
		    invoke stricmp,addr path,addr [di].wp_path
		    pop dx
		    .if !ax
			mov [di],dx
		    .endif
		    or	ax,ax
		.endif
	      endif
	    .endif
	    .if [si].pn_flag & _P_VISIBLE
		mov ax,si
		call panel_reread
		.if si == cpanel
		    mov ax,si
		    call panel_setactive
		.endif
	    .endif
	    mov ax,1
	.endif
	ret
panel_open endp

panel_open_ab proc
	mov ax,cpanel
	call panel_open
	.if ax
	    mov ax,offset spanelb
	    .if cpanel == ax
		mov ax,offset spanela
	    .endif
	    call panel_open
	    mov ax,1
	.endif
	ret
panel_open_ab endp

panel_close proc
	push	si
	mov	si,ax
	call	panel_state
	push	ax
	mov	ax,dx
	call	prect_close
	invoke	wsclose,[si].pn_wsub
	pop	ax
	pop	si
	ret
panel_close endp

panel_hide proc
	push	ax
	call	prect_close
	pop	bx
	push	ax
	invoke	wsfree,[bx].pn_wsub
	pop	ax
	ret
panel_hide endp

panel_show proc
	mov	bx,ax
	or	[bx].pn_flag,_P_VISIBLE
	call	panel_update
	ret
panel_show endp

panel_setactive proc
	push si
	push di
	mov si,ax
	mov di,cpanel
	and cflag,not _C_PANELID
	.if [si].pn_flag & _P_PANELID
	    or cflag,_C_PANELID
	.endif
	invoke cominit, [si].pn_wsub
	invoke dlclose, [di].pn_xl
	mov cpanel,si
	mov ax,di
	call panel_putinfo
	.if cflag & _C_WIDEVIEW && si != di
	    mov ax,di
	    call prect_hide
	    mov ax,si
	    call panel_redraw
	.else
	    mov ax,si
	    call pcell_show
	    mov ax,si
	    call panel_putinfo
	.endif
	pop di
	pop si
	ret
panel_setactive endp

panel_curobj proc
	mov bx,ax
	mov ax,word ptr [bx].pn_wsub
	.if ax
	    mov ax,[bx].pn_fcb_index
	    add ax,[bx].pn_cel_index
	    invoke wsfblk,[bx].pn_wsub,ax
	.endif
	ret
panel_curobj endp

panel_findnext proc
	mov bx,ax
	invoke wsffirst,[bx].pn_wsub
	ret
panel_findnext endp

panel_selected proc
	push ds
	push si
	mov bx,ax
	xor ax,ax
	mov cx,[bx].pn_fcb_count
	.if cx
	    push ds
	    pop es
	    mov	bx,word ptr [bx].pn_wsub
	    lds	si,[bx].ws_fcb
	    .if si
		.while cx
		    les bx,[si]
		    .if es:[bx].fb_flag & _A_SELECTED
			inc ax
		    .endif
		    add si,4
		    dec cx
		.endw
	    .endif
	.endif
	pop si
	pop ds
	ret
panel_selected endp

panel_setid proc	; panel:AX, index:DX
	push ax
	push dx
	mov bx,ax
	xor ax,ax
	mov [bx].pn_cel_index,ax
	mov [bx].pn_fcb_index,ax
	mov ax,bx
	call pcell_set
	pop ax
	pop bx
	.if ax < [bx].pn_cel_count
	    mov [bx].pn_cel_index,ax
	.else
	    sub ax,[bx].pn_cel_count
	    inc ax
	    mov [bx].pn_fcb_index,ax
	    mov ax,[bx].pn_cel_count
	    dec ax
	    mov [bx].pn_cel_index,ax
	.endif
	ret
panel_setid endp

panel_openmsg proc
	push	si
	mov	si,ax
	mov	bx,word ptr [si].pn_dialog
	test	[bx].dl_flag,_D_ONSCR
	jz	@F
	sub	ax,ax
	cmp	word ptr [bx].dl_wp,ax
	je	@F
	mov	ax,[si].pn_flag
	and	ax,_P_MINISTATUS
	jz	@F
	mov	ax,[bx+4]
	add	ah,[bx+7]
	sub	ah,2
	inc	al
	mov	cl,[bx+6]
	sub	cl,2
	mov	ch,0
	mov	bx,ax
	mov	ah,at_background[B_Desktop]
	or	ah,at_foreground[F_System]
	mov	al,' '
	call	@scputw
	push	cx
	mov	cx,5
	scputs@ bl, bh, ch, cl, ds, offset cp_openmsg
	mov	ax,[si]
	add	ax,wp_path
	pop	cx
	sub	cl,6
	add	bl,6
	scpath@ bl, bh, cx, ds, ax
      @@:
	pop	si
	ret
panel_openmsg endp

panel_putinfo proc pascal uses si di
local	path[WMAXPATH]:byte
local	xy:word
	call panel_state
	.if ax
	    mov di,dx
	    mov si,word ptr [di].pn_dialog
	    .if [si].dl_flag & _D_ONSCR
		mov si,[di]
		mov bx,word ptr [di].pn_dialog
		mov ax,[bx+4]
		mov xy,ax
		invoke strcpy,addr path,addr [si].wp_path
	      ifdef __LFN__
		invoke wlongpath, dx::ax, 0
	      endif
	      ifdef __ARC__
		.if [si].wp_flag & _W_ARCHIVE or _W_ROOTDIR
		    invoke strfcat,dx::ax,addr [si].wp_file,addr [si].wp_arch
		.endif
	      endif
		invoke dostounix, dx::ax
		mov dx,ax
		mov bx,xy
		add bx,0101h
		mov ah,at_background[B_Desktop]
		or  ah,at_foreground[F_Panel]
		mov al,[si.wp_path]
		scputw@	bl, bh, 1, ax
		mov cx,38
		.if cflag & _C_HORIZONTAL
		    mov cx,78
		.endif
		push cx
		push dx
		dec bh
		mov ah,at_background[B_Desktop]
		or  ah,at_foreground[F_Frame]
		mov al,205
		call @scputw
		invoke strlen, ds::dx
		mov dx,ax
		pop ax
		pop bx
		mov ch,at_background[B_Desktop]
		or  ch,at_foreground[F_Files]
		.if di == cpanel
		    mov ch,at_background[B_DarkGray]
		    or  ch,at_foreground[F_Black]
		.endif
		dec bx
		.if dx >= bx
		    mov cl,bl
		    inc cl
		    mov bx,xy
		    inc bl
		    push ax
		    mov ch,0
		    scputw@ bl, bh, cx, ' '
		    inc bl
		    sub cl,2
		    pop ax
		    scpath@ bl, bh, cx, ds, ax
		.else
		    mov si,ax
		    mov al,bl
		    shr dl,1
		    adc dl,0
		    shr al,1
		    adc al,0
		    mov bx,xy
		    add bl,al
		    sub bl,dl
		    scputf@ bl, bh, ch, 0, offset cp_pinfo0, si, ds
		.endif
	    .endif
	.endif
	ret
panel_putinfo endp

;----------------------------------------------------------------------------
; Ministatus window(s)
;----------------------------------------------------------------------------

ministatus_putselected:
      ifdef __386__
	xor eax,eax
	mov qeax,eax
	mov qedx,eax
      else
	xor ax,ax
	mov word ptr qeax+2,ax
	mov word ptr qeax,ax
	mov word ptr qedx+2,ax
	mov word ptr qedx,ax
      endif
	mov cx,[si].pn_fcb_count
	.if cx
	    mov bx,word ptr [si].pn_wsub
	    .if word ptr [bx].ws_fcb != ax
		push bp
		push di
		push si
		mov di,ax
		les si,[bx].ws_fcb
		mov bp,es
		.while cx
		    mov	es,bp
		    les bx,es:[si]
		    mov ax,es:[bx].fb_flag
		    .if ax & _A_SELECTED
			inc di
			.if !(al & _A_SUBDIR)
		      ifdef __386__
			    mov eax,es:[bx].fb_size
			    add qeax,eax
			    adc qedx,0
		      else
			    lodm es:[bx].fb_size
			    add word ptr qeax,ax
			    adc word ptr qeax+2,dx
			    adc word ptr qedx,0
			    adc word ptr qedx+2,0
		      endif
			.endif
		    .endif
		    add si,4
		    dec cx
		.endw
		mov cx,di
		pop si
		pop di
		pop bp
		push cx
		push ss
		push di
		invoke mkbstring, ss::di, qedx, qeax
		mov ch,at_background[B_Desktop]
		or  ch,at_foreground[F_Panel]
		mov cl,0
		mov bx,[bp-6]
		inc bl
		mov ax,offset cp_bselected
		call @scputf
		add sp,6
	    .endif
	.endif
	ret

volinfo_clear:
	mov bx,[bp-6]
	sub bh,2
	inc bl
	mov [bp-6],bx
	.if cflag & _C_HORIZONTAL
	    add bl,40
	.endif
	call @F
	inc bh
	call @F
	dec bh
	.if cflag & _C_HORIZONTAL
	    sub bl,40
	.else
	    dec bh
	.endif
	call @F
	ret
    @@:
	mov cx,37
	mov ah,at_background[B_Desktop]
	or  ah,at_foreground[F_Panel]
	mov al,' '
	call @scputw
	ret

volinfo_putinfo:
	mov bx,[bp-6]
	.if (cflag & _C_HORIZONTAL)
	    add bl,40
	.endif
	scputf@ bl, bh, 0, 0, offset CP_VIFREE
	add bl,32
	scputf@ bl, bh, ch, cl, offset CP_VIBYTE
	inc bh
	scputf@ bl, bh, ch, cl, offset CP_VIBYTE
	ret

volinfo_getdisk:
	mov bx,[si]
	add bx,wp_path
	mov ax,[bx]
	mov CP_VIDISK,al
	.if al && ah == ':'
	    and al,not 20h
	    mov CP_VIDISK,al
	    sub al,'@'
	    mov DB_VIDISK,al
	.else
	    mov DB_VIDISK,0FFh
	.endif
	ret

volinfo_putvolid:
	call volinfo_getdisk
	.if DB_VIDISK != 0FFh
	    mov ax,word ptr CP_VIDISK
	    mov [di],ax
	    mov ax,'*\'
	    mov [di+2],ax
	    mov ax,'*.'
	    mov [di+4],ax
	    mov byte ptr [di+6],0
	    invoke findfirst, ss::di, ss::di, _A_VOLID
	    or ax,ax
	    jnz @F
	.endif
	mov dx,ss
	mov ax,di
	add ax,ff_name
	mov ch,at_background[B_Desktop]
	or  ch,at_foreground[F_Files]
	mov cl,0
	.if DB_VIDISK == 0FFh
	@@:
	    mov ch,at_background[B_Desktop]
	    or  ch,at_foreground[F_Hidden]
	    mov ax,offset CP_NONAME
	    mov dx,ds
	.endif
	mov bx,[bp-6]
	.if !(cflag & _C_HORIZONTAL)
	    dec bh
	.endif
	call @scputs
	ret

volinfo_putlfn:
      ifdef __LFN__
	invoke wvolinfo, addr CP_VIDISK, ss::di
	.if !ax
	    push ss
	    push di
	    mov ax,offset format_24s
	    mov cl,24
	    mov ch,at_background[B_Desktop]
	    or  ch,at_foreground[F_Subdir]
	    mov bx,[bp-6]
	    add bl,12
	    .if !(cflag & _C_HORIZONTAL)
		dec bh
	    .endif
	    call @scputf
	    add sp,4
	.endif
      endif
	ret

ministatus_putvolinfo:
	call volinfo_clear
	call volinfo_putinfo
	call volinfo_putvolid
	call volinfo_putlfn
	invoke memzero, ss::di, SIZE S_DISKFREE
	push ss
	pop es
	stc
	mov ax,7303h
	mov cx,44
	mov dx,offset CP_VIDISK
	int 21h
	.if CARRY?
	    .if al
		ret
	    .endif
	    mov dl,DB_VIDISK
	    mov ah,36h
	    int 21h
	    .if ax == -1
		ret
	    .endif
	    mov word ptr [di].df_sclus,ax
	    mov word ptr [di].df_avail,bx
	    mov word ptr [di].df_bsec, cx
	    mov word ptr [di].df_total,dx
	.endif
	lodm [di.df_sclus]
	push ax
	push dx
	mov bx,word ptr [di].df_total
	mov cx,word ptr [di].df_total[2]
	call MUL32
	mov bx,word ptr [di].df_bsec
	mov cx,word ptr [di].df_bsec[2]
	call MUL32
	add di,SIZE S_DISKFREE
	invoke mkbstring, ss::di, cx::bx, dx::ax
	pop dx
	pop ax
	sub di,SIZE S_DISKFREE
	mov bx,word ptr [di].df_avail
	mov cx,word ptr [di].df_avail[2]
	call MUL32
	mov bx,word ptr [di].df_bsec
	mov cx,word ptr [di].df_bsec[2]
	call MUL32
	add di,SIZE S_DISKFREE + 20
	invoke mkbstring,ss::di,cx::bx,dx::ax
	push ss
	mov ax,di
	sub di,20
	push di
	push ss
	push ax
	mov ch,at_background[B_Desktop]
	or  ch,at_foreground[F_Files]
	mov cl,0
	mov bx,[bp-6]
	add bl,11
	.if cflag & _C_HORIZONTAL
	    add bl,40
	.endif
	mov ax,offset format_20s
	call @scputf
	add sp,4
	inc bh
	mov ax,offset format_20s
	call @scputf
	add sp,4
	ret

panel_putmini proc pascal uses si di
local	path[138]:byte
	mov si,ax
	mov di,word ptr [si].pn_dialog
	.if [di].dl_flag & _D_ONSCR
	    call panel_state
	    .if ax
		mov bx,di
		lea di,[bp-138]
		mov cx,[bx+6]
		mov bx,[bx+4]
		inc bl
		add bh,ch
		sub bh,2
		mov [bp-6],bx
		xor ax,ax
		mov al,bl
		mov [bp-2],ax
		mov al,bh
		mov [bp-4],ax
		mov bx,[si]
		mov ax,[si].pn_flag
		.if ax & _P_MINISTATUS
		    .if ax & _P_DRVINFO
			push cx
			push [bp-6]
			call ministatus_putvolinfo
			pop bx
			mov [bp-6],bx
			pop cx
		    .endif
		    mov ch,0
		    sub cl,2
		    mov bl,[bp-2]
		    mov bh,[bp-4]
		    mov ah,at_background[B_Desktop]
		    or  ah,at_foreground[F_Hidden]
		    mov al,' '
		    mov dx,ax
		    call @scputw
		    xor cx,cx
		    mov ch,dh
		    .if [si].pn_fcb_count == 0
			mov dx,bx
			mov bx,[si]
			mov bl,[bx].wp_path
			push bx
			mov bx,dx
			mov ax,offset cp_emptydisk
			call @scputf
			add sp,2
		    .else
			mov ax,[si].pn_fcb_index
			add ax,[si].pn_cel_index
			invoke wsfblk,[si].pn_wsub,ax
			mov [bp-8],dx
			mov [bp-10],bx
			mov ax,si
			call panel_selected
			.if ax
			    call ministatus_putselected
			.else
			    push [bp-8]
			    push [bp-10]
			    push [bp-2]
			    push [bp-4]
			  ifdef __LFN__
			    .if cflag & _C_HORIZONTAL && _ifsmgr != 0
				call fbputld
			    .else
				call fbputfile
			    .endif
			  else
				call fbputfile
			  endif
			     les bx,[bp-10]
			     .if es:[bx].fb_flag & _A_UPDIR
				mov bx,[bp-6]
				mov cx,2
				mov ax,' '
				call @scputw
				mov si,[si]
				invoke strfn,addr [si].wp_path
				mov ch,at_background[B_Desktop]
				or  ch,at_foreground[F_System]
				mov cl,12
				mov bx,[bp-6]
				call @scputs
			    .endif
			.endif
		    .endif
		.endif
	    .endif
	.endif
	ret
panel_putmini endp

panel_putitem proc pascal uses si di panel:word, index:word
local	rc:dword
local	result:word
local	count:word
	mov si,panel
	mov di,word ptr [si].pn_dialog
	.if [di].dl_flag & _D_ONSCR
	    movmx rc,[di].dl_rect
	    mov ax,[si].pn_flag
	    .if ax & _P_MINISTATUS
		sub rc.rc_row,2
		.if ax & _P_DRVINFO
		    sub rc.rc_row,3
		    .if cflag & _C_HORIZONTAL
			inc rc.rc_row
		    .endif
		.endif
	    .endif
	    mov ax,[si].pn_fcb_count
	    .if ax
		invoke dlclose, [si].pn_xl
		mov result,ax
		mov ax,si
		call pcell_set
		invoke prect_clear, rc, index
		mov bx,word ptr [si].pn_dialog
		xor ax,ax
		mov dx,ax
		mov dl,[bx+5]
		mov di,dx
		dec ax
		mov count,ax
		.while 1
		    inc count
		    mov ax,count
		    .if ax >= [si].pn_cel_count
			.if result
			    mov ax,si
			    call pcell_show
			.endif
			mov ax,si
			call panel_putmini
			.break
		    .endif
		    invoke xcell_getrect, [si].pn_xl, count
		    mov dx,index
		    .if dx == 1
			mov bx,word ptr [si].pn_xl
			mov dx,di
			add dl,[bx].xl_rows
			inc dl
		    .elseif dx == 2
			mov dx,di
			add dx,2
		    .else
			mov dl,ah
		    .endif
		    .if ah == dl
			mov bx,word ptr [si].pn_wsub
			les bx,[bx].ws_fcb
			mov dx,[si].pn_fcb_index
			add dx,count
			shl dx,2
			add bx,dx
			pushm es:[bx]
			xor  dx,dx
			mov  dl,al
			push dx
			mov  dl,ah
			push dx
			call [si].pn_putfcb
		    .endif
		.endw
	    .else
		invoke prect_clear,rc,0
	    .endif
	.endif
	ret
panel_putitem endp

ifdef __ROT__

if 0
wsreaddoc proc pascal uses si di wsub:dword
	invoke	fbupdir,_A_ROOTDIR
	les	bx,wsub
	inc	es:[bx].ws_count
	les	bx,es:[bx].ws_fcb
	stom	es:[bx]
	call	tigetfile
	mov	si,ax
      @@:
      	test	si,si
	jz	@F
	invoke	strfn,[si].ti_file
	invoke	fballoc,dx::ax,[si].ti_time,si,[si].ti_size,_A_ROOTDIR
	les	bx,wsub
	mov	cx,es:[bx].ws_count
	inc	es:[bx].ws_count
	shl	cx,2
	les	bx,es:[bx].ws_fcb
	add	bx,cx
	stom	es:[bx]
	mov	ax,[si].ti_next
	cmp	si,ax
	jae	@F
	mov	si,ax
	jmp	@B
      @@:
	les	bx,wsub
	mov	ax,es:[bx].ws_count
	ret
wsreaddoc endp
endif

wsreadroot proc pascal uses si di wsub:dword, panel:word
local	dtime:	word
local	ddate:	word
local	disk:	word
local	index:	word
	invoke	wsfree,wsub
	xor	ax,ax
	mov	disk,ax
	mov	index,ax
	les	bx,wsub
	les	bx,es:[bx].ws_flag
	mov	ax,es:[bx].wp_flag
	and	ax,not (_W_ARCHIVE or _W_NETWORK)
	or	ax,_W_ROOTDIR
	mov	es:[bx].wp_flag,ax
	mov	ax,sys_ercode
	or	al,sys_erflag
	or	al,sys_erdrive
	jnz	@F
	call	getdrv
	mov	disk,ax
      @@:
	xor ax,ax
	mov es:[bx].wp_arch,al
	invoke strcpy,addr es:[bx].wp_file,addr cp_rot
	xor di,di
	xor si,si
	.while si < MAXDRIVES
	    .if func(_disk_type,si)
		mov ax,si
		mov ah,SIZE S_DISK
		mul ah
		mov bx,ax
		add bx,offset drvinfo
		.if func(fballoc,
		    addr [bx].di_name,
		    [bx].di_time,
		    [bx].di_date,
		    [bx].di_sizeax,
		    [bx].di_flag)
		    les bx,wsub
		    les bx,es:[bx].ws_fcb
		    mov cx,di
		    shl cx,2
		    add bx,cx
		    stom es:[bx]
		    .if si == disk
			mov index,di
		    .endif
		    inc di
		.endif
	    .endif
	    inc si
	.endw
	les bx,wsub
	mov es:[bx].ws_count,di
	mov ax,di
	mov dx,index
	ret
wsreadroot endp

endif

panel_read proc
	push si
	mov  si,ax
	call panel_openmsg
     ifdef __ROT__
	mov  bx,[si]
	.if [bx].wp_path && [bx].wp_flag & _W_ROOTDIR
	    invoke wsreadroot,[si].pn_wsub,si
	    mov [si].pn_cel_index,dx
	.else
	    invoke wsread,[si].pn_wsub
	.endif
     else
	invoke wsread,[si].pn_wsub
     endif
	mov [si].pn_fcb_count,ax
	.if ax <= [si].pn_fcb_index
	    dec ax
	    mov [si].pn_fcb_index,ax
	    inc ax
	.endif
	pop si
	ret
panel_read endp

panel_reread proc
	push	si
	mov	si,ax
	mov	ax,[si].pn_flag
	and	ax,_P_VISIBLE
	jz	@F
	mov	ax,si
	call	panel_read
	xor	ax,ax
	call	panel_putinfo_AX
	mov	ax,1
      @@:
	pop	si
	ret
panel_reread endp

panel_redraw proc
	push si
	mov si,ax
	mov ax,[si].pn_flag
	and ax,_P_VISIBLE
	.if ax
	    mov ax,si
	    call prect_open
	    xor ax,ax
	    call panel_putinfo_AX
	    mov ax,1
	    .if si == cpanel
		mov ax,si
		call pcell_show
	    .endif
	.endif
	pop si
	ret
panel_redraw endp

redraw_panels proc
	mov ax,panelb
	call prect_hide
	push ax
	mov ax,panela
	call panel_redraw
	pop ax
	.if ax
	    mov ax,panelb
	    mov bx,ax
	    or [bx].pn_flag,_P_VISIBLE
	    call panel_redraw
	.endif
	ret
redraw_panels endp

panel_toggle proc
	push si
	mov  si,ax
	call panel_state
	.if !ZERO?
	    .if dx == cpanel
		mov ax,offset spanela
		.if ax == dx
		    mov ax,offset spanelb
		.endif
		call panel_state
		.if !ZERO?
		    mov ax,dx
		    call panel_setactive
		.endif
	    .endif
	    mov ax,si
	    call panel_hide
	.else
	    mov ax,si
	    call panel_show
	    .if si != cpanel
		mov ax,cpanel
		call panel_state
		jnz @F
	    .endif
	    mov ax,si
	    call panel_setactive
	.endif
    @@:
	xor ax,ax
	pop si
	ret
panel_toggle endp

panel_update proc
	push si
	mov si,ax
	mov ax,[si].pn_flag
	and ax,_P_VISIBLE
	.if ax
	    mov ax,si
	    call panel_read
	    mov ax,si
	    call panel_redraw
	.endif
	pop si
	ret
panel_update endp

panel_xormini proc
	mov bx,ax
	mov ax,[bx].pn_flag
	xor ax,_P_MINISTATUS
	mov [bx].pn_flag,ax
	test ax,_P_VISIBLE
	mov ax,bx
	.if !ZERO?
	    call panel_redraw
	.endif
	call msloop
	xor ax,ax
	ret
panel_xormini endp

panel_xorinfo proc
	push si
	mov si,ax
	mov ax,[si].pn_flag
	xor ax,_P_DRVINFO
	.if ax & _P_DRVINFO
	    or ax,_P_MINISTATUS
	.endif
	mov [si].pn_flag,ax
	mov ax,si
	call panel_redraw
	pop si
	ret
panel_xorinfo endp

panel_xycmd proc pascal uses si di panel:word, xpos:word, ypos:word
    local rect:dword
    local endx:word
	mov ax,panel
	.if func(panel_state)
	    dec ax
	    mov si,dx
	    mov di,word ptr [si].pn_dialog
	    .if [di].dl_flag & _D_ONSCR
		movmm rect,[di].dl_rect
		sub ah,ah
		add al,rect.rc_col
		dec al
		mov endx,ax
		invoke rcxyrow, rect, xpos, ypos
		mov dx,ax
		sub ax,ax
		.if dx
		    .if dx == 1
			mov ax,_XY_MOVEUP
		    .else
			mov di,dx
			.if dx == 2
			    mov dl,rect.rc_x
			    .if xpos == dx
				mov ax,_XY_INSIDE
			    .else
				add dx,2
				.if xpos <= dx
				    mov ax,_XY_NEWDISK
				.else
				    inc dx
				    .if dx == xpos
					mov ax,_XY_CONFIG
				    .else
					mov ax,_XY_MOVEUP
				    .endif
				.endif
			    .endif
			.else
			    mov bx,[si]
			    .if [si].pn_flag & _P_MINISTATUS
				mov dl,rect.rc_row
				sub dl,2
				.if [si].pn_flag & _P_DRVINFO
				    sub dl,2
				    .if !(cflag & _C_HORIZONTAL)
					dec dl
				    .endif
				.endif
				mov rect.rc_row,dl
				.if di > dx
				    mov ax,_XY_MOVEDOWN
				.elseif di != dx
				    jmp panel_xycmd_11
				.else
				    mov dl,rect.rc_x
				    add dl,2
				    .if xpos == dx
					mov ax,_XY_DRVINFO
				    .else
					jmp panel_xycmd_01
				    .endif
				.endif
			    .else
				mov dl,rect.rc_row
				.if dx != di
				  panel_xycmd_11:
				    xor di,di
				    .while di < [si].pn_cel_count
					invoke xcell_getrect,[si].pn_xl,di
					invoke rcxyrow,dx::ax,xpos,ypos
					mov ax,_XY_INSIDE
					.if !ZERO?
					    mov ax,_XY_FILE
					    .break
					.endif
					inc di
				    .endw
				.else
				  panel_xycmd_01:
				    mov dx,endx
				    sub dx,2
				    .if dx == xpos
					mov ax,_XY_MINISTATUS
				    .else
					mov ax,_XY_MOVEDOWN
				    .endif
				.endif
			    .endif
			.endif
		    .endif
		.endif
	    .endif
	.endif
	ret
panel_xycmd endp

panel_putinfo_ZX:
	sub ax,ax
	mov [si].pn_cel_index,ax
	mov [si].pn_fcb_index,ax

panel_putinfo_AX:
	push ax
	mov ax,si
	call panel_putinfo
	pop ax

panel_putitem_AX:
	invoke panel_putitem,si,ax
	mov ax,1
	ret

panel_sethdd proc pascal uses si di panel:word, hdd:word
	call getdrv
	mov di,ax
	mov si,panel
	invoke _disk_init, hdd
	pushm [si].pn_wsub
	push ax
	call history_save
	call wschdrv
	mov ax,si
	call panel_read
	.if si == cpanel
	    invoke cominit,[si].pn_wsub
	.else
	    mov	dx,di
	    mov	ah,0Eh
	    int	21h
	.endif
	call panel_putinfo_ZX
	ret
panel_sethdd endp

cpanel_findfirst proc
	mov ax,cpanel
	call panel_state
	.if !ZERO?
	    mov ax,dx
	    call panel_findnext
	    .if ZERO?
		mov ax,cpanel
		call panel_curobj
	    .endif
	    .if !ZERO? && !(cx & _A_UPDIR)
		or ax,ax
		ret
	    .endif
	.endif
	xor ax,ax
	ret
cpanel_findfirst endp

cpanel_gettarget proc
	call panel_stateab
	.if !ZERO?
	    mov dx,ds
	    mov ax,offset path_a.wp_path
	    .if cpanel == offset spanela
		mov ax,offset path_b.wp_path
	    .endif
	.endif
	or ax,ax
	ret
cpanel_gettarget endp

cpanel_setpath proc	; DX:AX
	mov	bx,cpanel
	mov	bx,[bx]
	and	word ptr [bx],not (_W_NETWORK or _W_ARCHIVE or _W_ROOTDIR)
	add	bx,wp_path
	invoke	strcpy,ds::bx,dx::ax
	mov	bx,cpanel
	invoke	cominit,[bx].pn_wsub
	mov	ax,cpanel
	call	panel_reread
	ret
cpanel_setpath endp

cpanel_deselect	proc pascal uses si di fblk:dword
	les bx,fblk
	and es:[bx].fb_flag,not _A_SELECTED
	mov di,progress_dobj.dl_flag
	and di,_D_ONSCR
	.if !ZERO?
	    invoke dlhide, addr progress_dobj
	.endif
	invoke panel_putitem, cpanel, 0
	mov si,offset spanela
	.if si == cpanel
	    mov si,offset spanelb
	.endif
	mov bx,word ptr [si].pn_wsub
	mov ax,[bx].ws_maxfb
	sub ax,2
	.if ax > [bx].ws_count
	    lodm fblk
	    add ax,fb_name
	    invoke strlen, dx::ax
	    add ax,SIZE S_FBLK
	    push ax
	    invoke malloc, ax
	    pop bx
	    .if ax
		invoke memcpy, dx::ax, fblk, bx
		inc [si].pn_fcb_count
		inc [si].pn_cel_count
		mov bx,word ptr [si].pn_wsub
		mov cx,[bx].ws_count
		inc [bx].ws_count
		les bx,[bx].ws_fcb
		shl cx,2
		add bx,cx
		stom es:[bx]
		invoke panel_event, si, KEY_END
	    .endif
	.endif
	.if di
	    invoke dlshow, addr progress_dobj
	.endif
	ret
cpanel_deselect endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

panelevent_updatecell proc
	mov ax,si
	call pcell_update
	ret
panelevent_updatecell endp

panelevent_LEFT proc
	mov bx,word ptr [si].pn_xl
	xor ax,ax
	cwd
	mov al,[bx+3]
	.if ax <= [si].pn_cel_index
	    sub [si].pn_cel_index,ax
	    jmp panelevent_updatecell
	.endif
	.if [si].pn_cel_index != dx
	    mov [si].pn_cel_index,dx
	    jmp panelevent_updatecell
	.endif
	.if [si].pn_fcb_index == dx
	    xor ax,ax
	    ret
	.endif
	.if ax <= [si].pn_fcb_index
	    sub [si].pn_fcb_index,ax
	.else
	    mov [si].pn_fcb_index,dx
	.endif
	mov ax,dx
	jmp panel_putitem_AX
panelevent_LEFT endp

panelevent_RIGHT proc
	mov bx,word ptr [si].pn_xl
	xor cx,cx
	mov cl,[bx+3]
	mov ax,[si].pn_cel_index
	add ax,cx
	mov dx,[si].pn_cel_count
	dec dx
	.if ax <= dx
	    add [si].pn_cel_index,cx
	    jmp panelevent_updatecell
	.endif
	mov ax,[si].pn_cel_index
	add ax,[si].pn_fcb_index
	add ax,cx
	.if ax < [si].pn_fcb_count
	    add [si].pn_fcb_index,cx
	    xor ax,ax
	    jmp panel_putitem_AX
	.endif
	.if [si].pn_cel_index < dx
	    mov [si].pn_cel_index,dx
	    jmp panelevent_updatecell
	.endif
	xor ax,ax
	ret
panelevent_RIGHT endp

panelevent_UP proc
	xor ax,ax
	.if [si].pn_cel_index != ax
	    dec [si].pn_cel_index
	    jmp panelevent_updatecell
	.endif
	.if [si].pn_fcb_index == ax
	    ret
	.endif
	dec [si].pn_fcb_index
	mov ax,2
	jmp panel_putitem_AX
panelevent_UP endp

panelevent_DOWN proc
	mov ax,[si].pn_cel_count
	dec ax
	cmp ax,[si].pn_cel_index
	jbe @F
	inc [si].pn_cel_index
	jmp panelevent_updatecell
      @@:
	jne @F
	mov ax,[si].pn_fcb_count
	sub ax,[si].pn_fcb_index
	sub ax,[si].pn_cel_index
	cmp ax,1
	jle @F
	inc [si].pn_fcb_index
	mov ax,1
	jmp panel_putitem_AX
      @@:
	xor ax,ax
	ret
panelevent_DOWN endp

panelevent_INS proc
	mov ax,si
	call pcell_select
	.if ax
	    .if cflag & _C_INSMOVDN
		jmp panelevent_DOWN
	    .endif
	    mov ax,1
	.endif
	ret
panelevent_INS endp

panelevent_END proc
	mov dx,[si].pn_cel_count
	mov ax,[si].pn_fcb_count
	.if dx < ax
	    sub ax,dx
	    mov [si].pn_fcb_index,ax
	    dec dx
	    mov [si].pn_cel_index,dx
	    xor ax,ax
	    jmp panel_putitem_AX
	.else
	    xor ax,ax
	    dec dx
	    .if dx > [si].pn_cel_index
		mov [si].pn_cel_index,dx
		mov [si].pn_fcb_index,ax
		jmp panel_putitem_AX
	    .else
		ret
	    .endif
	.endif
panelevent_END endp

panelevent_HOME proc
	xor ax,ax
	mov dx,[si].pn_cel_index
	or  dx,[si].pn_fcb_index
	.if dx
	    mov [si].pn_cel_index,ax
	    mov [si].pn_fcb_index,ax
	    jmp panel_putitem_AX
	.endif
	ret
panelevent_HOME endp

panelevent_PGUP proc
	xor ax,ax
	mov dx,[si].pn_cel_index
	or  dx,[si].pn_fcb_index
	.if dx
	    .if [si].pn_cel_index != ax
		mov [si].pn_cel_index,ax
		jmp panelevent_updatecell
	    .endif
	    mov cx,ax
	    mov bx,word ptr [si].pn_xl
	    mov al,[bx+2]
	    mov cl,[bx+3]
	    imul cx
	    .if ax <= [si].pn_fcb_index
		sub [si].pn_fcb_index,ax
	    .else
		mov [si].pn_fcb_index,0
	    .endif
	    xor ax,ax
	    jmp panel_putitem_AX
	.endif
	ret
panelevent_PGUP endp

panelevent_PGDN proc
	mov ax,[si].pn_cel_count
	dec ax
	.if ax != [si].pn_cel_index
	    mov [si].pn_cel_index,ax
	    jmp panelevent_updatecell
	.endif
	add ax,[si].pn_fcb_index
	inc ax
	.if ax == [si].pn_fcb_count
	  @@:
	    xor ax,ax
	    ret
	.endif
	mov ax,[si].pn_fcb_index
	add ax,[si].pn_cel_count
	cmp ax,[si].pn_fcb_count
	jnb @B
	mov ax,[si].pn_cel_count
	dec ax
	add [si].pn_fcb_index,ax
	xor ax,ax
	mov [si].pn_cel_index,ax
	jmp panel_putitem_AX
panelevent_PGDN endp

;----------------------------------------------------------------------------
; Panel Event ENTER
;----------------------------------------------------------------------------

S_PEVENT STRUC
pe_fblk	 dd ?
pe_name	 dd ?
pe_flag	 dw ?
pe_panel dw ?
pe_event dw ?
pe_file	 db WMAXPATH dup(?)
pe_path	 db WMAXPATH dup(?)
S_PEVENT ENDS

panel_savepath proc
	push	cx
	push	dx
	push	ss
	lea	ax,[bp].pe_file
	push	ax
	mov	ax,di
      ifdef __ARC__
	.if cx & _W_ARCHIVE or _W_ROOTDIR
	    .if [di].wp_arch
		add ax,wp_arch
		jmp panel_savepath_00
	    .else
		add ax,wp_file
		mov dx,ds
		jmp panel_savepath_01
	    .endif
	.endif
      endif
      ifdef __LFN__
	.if cx & _W_LONGNAME
	    add ax,wp_path
	    invoke wlongname,ds::ax,0
	    jmp panel_savepath_01
	.endif
      endif
	add	ax,wp_path
    panel_savepath_00:
	invoke	strfn,ds::ax
    panel_savepath_01:
	push	dx
	push	ax
    panel_savepath_02:
	call	strcpy
	pop	dx
	pop	cx
	ret
panel_savepath endp

ifdef __ROT__

panel_enter_rootdir proc
	mov [di].wp_arch,0
	.if !(cx & _A_UPDIR)
	    invoke strcpy,addr [di].wp_arch,[bp].pe_name
	.endif
	or [di].wp_flag,_W_ROOTDIR
	jmp panel_enter_read
panel_enter_rootdir endp

endif

panel_enter_local proc
      ifdef __ROT__
	test [bp].pe_flag,_A_ROOTDIR
	jnz panel_enter_rootdir
      endif
	invoke strfcat,addr [bp].pe_path,addr [di].wp_path,[bp].pe_name
	invoke chdir,addr [bp].pe_path
	inc ax
	.if ax
	    xor ax,ax
	    mov al,[di].wp_path
	    and al,not 20h
	    sub al,'@'
	    mov cx,ax
      ifdef __LFN__
	    .if _ifsmgr && [di].wp_flag & _W_LONGNAME
		invoke wfullpath,addr [di].wp_path,cx
	    .else
		invoke fullpath,addr [di].wp_path,cx
	    .endif
      else
	    invoke fullpath,addr [di].wp_path,cx
      endif
	.else
	    ret
	.endif
panel_enter_local endp

panel_enter_read proc
	invoke cominit,[si].pn_wsub
	mov ax,si
	call panel_read
	or si,si
	ret
panel_enter_read endp

panel_add_to_path:
	add bx,fb_name
	xor ax,ax
	.if [di] == al
	    invoke strcpy,ds::di,dx::bx
	.else
	    invoke strfcat,ds::di,ax::ax,dx::bx
	.endif
	ret

panel_reduce_path:
	invoke strrchr,ds::di,'\'
	mov bx,di
	.if ax
	    mov bx,ax
	    xor ax,ax
	.endif
	mov [bx],al
	ret

panel_enter_network:
	add di,wp_path
	.if cl & _A_UPDIR
	    mov ax,di
	    add ax,2
	    .if func(strrchr,ds::ax,'\')
		call panel_reduce_path
	    .endif
	.else
	    call panel_add_to_path
	.endif
	jmp panel_enter_read


ifdef __ARC__

panel_enter_archive:
	.if cx & _A_UPDIR
	    .if ![di].wp_arch
		and [di].wp_flag,not (_W_ARCHIVE or _W_ROOTDIR)
	      ifdef __DLL__
		call freeplugin
	      endif
	    .else
		add di,wp_arch
		call panel_reduce_path
	    .endif
	.else
	    add di,wp_arch
	    call panel_add_to_path
	.endif
	jmp panel_enter_read

endif

enter_directory_error:
	lea ax,[bp].pe_path
	mov dx,ds
	mov bx,offset cp_error_chdir
	mov cx,offset cp_chdir_format
	call errnomsg
	ret

panel_enter_directory:
	mov di,[si]
	.if [di].wp_path[1] != ':'
	    .if [di].wp_path != '\'
		jmp enter_directory_error
	    .endif
	.endif
      ifdef __ARC__
	.if !(cx & _A_ARCHIVE)
      endif
	    push cx
	    push dx
	    push bx
	    call history_save
	    pop bx
	    pop dx
	    pop cx
      ifdef __ARC__
	.endif
      endif
	xor ax,ax
	mov [bp].pe_file,al
	.if cl & _A_UPDIR
	    push bx
	    call panel_savepath
	    pop bx
	.endif
      ifdef __ARC__
	.if cx & _A_ARCHIVE
	    call panel_enter_archive
	.elseif [di].wp_path[1] == ':'
      else
	.if [di].wp_path[1] == ':'
      endif
	    call panel_enter_local
	    jz enter_directory_error
	.else
	    call panel_enter_network
	.endif
	.if !([bp.pe_flag] & _A_ROOTDIR)
	    xor ax,ax
	    mov [si].pn_cel_index,ax
	    mov [si].pn_fcb_index,ax
	    .if [bp].pe_file != al
		invoke wsearch,[si].pn_wsub,addr [bp].pe_file
		.if ax != -1
		    mov dx,ax
		    mov ax,si
		    call panel_setid
		.endif
	    .endif
	.endif
	xor ax,ax
	jmp panel_putinfo_AX

panelevent_Enter proc
	mov	ax,si
	call	panel_curobj
	stoso	[bp].pe_fblk,dx,bx
	stoso	[bp].pe_name,dx,ax
	mov	[bp].pe_flag,cx
	jnz	@F
	ret
      @@:
	test	cl,_A_SUBDIR
	jz	@F
	jmp	panel_enter_directory
      @@:
	test	cx,_A_ARCHIVE
	jz	panelevent_enter_root
  ifdef __DLL__
	mov	bx,[si]
	mov	ax,[bx]
	test	ax,_A_ARCHEXT
	jz	@F
	mov	cx,bx
	mov	bx,word ptr [si].pn_wsub
	mov	ah,_DLL_ENTER
	int	DLL
	jnc	panelevent_enter_read
      @@:
  endif
	xor	ax,ax
	ret
    panelevent_enter_root:
  ifdef __ROT__
	.if cx & _A_ROOTDIR
	    .if cx & _A_VOLID
		mov bx,cpanel
		mov bx,[bx]
		and [bx].wp_flag,not _W_ROOTDIR
		les bx,[bp].pe_name
		mov ah,0
		mov al,es:[bx]
		sub al,'A'
		invoke panel_sethdd,cpanel,ax
		mov ax,1
		ret
	    .endif
	.endif
  endif
	call isexec
	.if ax
	panel_enter_cmd:
	    lodm [bp].pe_name 	; exe/com/bat
      ifdef __LFN__
	    invoke wshortname,dx::ax
      endif
	    invoke command,dx::ax
	    ret
	.endif
	invoke fbinitype,[bp].pe_fblk,addr [bp].pe_file
      ifdef __DLL__
	.if ax == 1
	    ret
	.elseif ax
	    mov ax,cx
	    jmp panel_enter_plugin
	.endif
      else
	.if ax
	    mov ax,1
	    ret
	.endif
      endif
      ifdef __ARC__
	mov bx,[si]
	invoke strfcat,addr [bp].pe_file,addr [bx].wp_path,[bp].pe_name
	invoke readword,dx::ax
       ifdef __ZIP__
	.if ax == 4B50h	; 'PK'
	    mov	ax,_W_ARCHZIP
	    jmp panel_enter_extern
	.endif
       endif
       ifdef __DLL__
	.if ax
       panel_enter_plugin:
	    invoke loadplugin,dx::ax,[bp].pe_name
	    .if !ZERO?
		mov ax,_W_ARCHEXT
		jmp panel_enter_extern
	    .endif
	.endif
       endif
      endif ; __ARC__
	.if console & CON_NTCMD
	    jmp panel_enter_cmd
	.endif
	ret
      ifdef __ARC__
       panel_enter_extern:
	.if path_a.wp_flag & _W_ARCHIVE || path_b.wp_flag & _W_ARCHIVE
	    xor ax,ax
	    ret
	.endif
	mov di,[si]
	mov [di].wp_arch,0
	and [di].wp_flag,not _W_ARCHIVE
	or  [di].wp_flag,ax
	add di,wp_file
	invoke strcpy,ds::di,[bp].pe_name
      endif ; __ARC__
    panelevent_enter_read:
	mov  ax,si
	call panel_read
	call panel_putinfo_ZX
	ret
panelevent_Enter endp

;-----------------------------------------------------------------------------

panel_event proc pascal uses si di panel:word, event:word
local	pe:S_PEVENT
	push bp
	mov ax,panel
	call panel_state
	.if !ZERO?
	    mov pe.pe_panel,dx
	    mov ax,event
	    mov pe.pe_event,ax
	    lea bp,pe
	    mov si,dx
	    mov cx,pekey_count
	    xor bx,bx
	    .if ax == KEY_INS
		les bx,keyshift
		mov dl,es:[bx]
		.if dl & 3
		    xor ax,ax
		    jmp @F
		.endif
		xor bx,bx
	    .endif
	    .while cx
		.if ax == pekey_table[bx]
		    call peproc_table[bx]
		    jmp @F
		.endif
		add bx,2
		dec cx
	    .endw
	    xor ax,ax
	.endif
      @@:
	pop bp
	ret
panel_event endp

_DZIP	ENDS

_DATA	SEGMENT

pekey_table label word
	dw      KEY_LEFT
	dw      KEY_RIGHT
	dw      KEY_UP
	dw      KEY_INS
	dw      KEY_DOWN
	dw      KEY_END
	dw      KEY_HOME
	dw      KEY_PGUP
	dw      KEY_PGDN
	dw      KEY_ENTER
	dw      KEY_KPENTER

peproc_table label word
	dw	offset panelevent_LEFT
	dw	offset panelevent_RIGHT
	dw	offset panelevent_UP
	dw	offset panelevent_INS
	dw	offset panelevent_DOWN
	dw	offset panelevent_END
	dw	offset panelevent_HOME
	dw	offset panelevent_PGUP
	dw	offset panelevent_PGDN
	dw	offset panelevent_Enter
	dw	offset panelevent_Enter

pekey_count = (($ - offset peproc_table) / 2)

qeax	dd ?	; Selected size
qedx	dd ?

_DATA	ENDS

	END
