include	doszip/doszip.inc
include stdio.inc
include	string.inc
include	ini.inc
include	io.inc
include	iost.inc
include	dos.inc
include	disk.inc
include	errno.inc
include	conio.inc
include tinfo.inc
include	mouse.inc
include	progress.inc
include	malloc.inc
include	stdlib.inc
include	confirm.inc

ifdef	DEBUG
include doszip/dz.inc
__FAKEDZ__	= 1	; load a fake DZ.EXE for debug
else
__INI_LOAD__	= 1	; DZ.INI: [Load]
endif
	public	dzmain
	public	getinifile
	public	getcfgfile
	public	getcmdfile
	public	_stklen
	public	ifsmgr
	public	_bufin
	public	comspec
	public	envpath
	public	envtemp
	public	dzexe
	public	dzcount
	public	numfblock
	public	mainswitch
	public	dzexitcode
	public	programpath
	public	configpath
	public	configfile
	public	argvfile
	public	DLG_Menusline
	public	DLG_Commandline
	public	DLG_Statusline
	public	copy_flag
	public	copy_fast
	public	copy_filecount
	public	copy_subdcount
	public	opfilter
ifdef __DLL__
	public	freeplugin
	public	loadplugin
endif
	extrn	_argc:word
	extrn	_argv:word
	extrn	dzmodal:near
	extrn	menusinit_OIDD:near
	extrn	com_info:S_TINFO
	extrn	cp_dznotloaded:byte
	extrn	cp_initype:byte
	extrn	apishow:near
	extrn	apihide:near
	extrn	comargs:byte
	extrn	CRLF$:byte

_DATA	SEGMENT

_stklen		dw 5000h	; 20 480 byte
ifsmgr		db ?		; init value - DZ_ifsmgr
envconf		dd ?		; %DZ%
envtemp		dd ?		; %TEMP%
envpath		dd ?		; %PATH%
comspec		dd ?		; %COMSPEC%
dzexe		dd ?		; dz.exe
dzerrno		dw ?		; - last return code
dzerflag 	dw ?		; - error type
dzcount		dw ?		; - exec count - zero on first call
mainswitch 	dw ?		; program switch
dzexitcode 	dw ?		; return code (23 if exec)
numfblock 	dw MAXFBLOCK	; number of file pointers allocated
argvfile 	dw ?		; file/directory arg.
programpath 	db MAXPATH dup(?); %doszip%
configpath 	db MAXPATH dup(?); %doszip% | %dz% | /C<path>

; Configuration file: DZ.CFG

config		dw	VERSION
cflag		dw	_C_DEFAULT
		db	NOT _C_CONFMOVE
console		dw	331Fh
fsflag		db	IO_SEARCHSUB
tvflag		db	_TV_HEXOFFSET
teflag		dw	_T_TEDEFAULT
tepages		dw	128
telsize		dw	256
compressflag	db	0
ffflag		db	2
compresslevel	db	9
		db	0
cflaga		dw	_P_MINISTATUS or _P_VISIBLE
		dw	0,0
cflagb		dw	_P_PANELID or _P_MINISTATUS or _P_VISIBLE
		dw	0,0
path_a		dw	_W_SORTTYPE or _W_HIDDEN
		db	'*.*',0
		db	28 dup(?)
		db 	WMAXPATH dup(?)
		db 	WMAXPATH dup(?)
		db 	WMAXPATH dup(?)
path_b		dw 	_W_SORTTYPE or _W_HIDDEN
		db	'*.*',0
		db 	28 dup(?)
		db 	WMAXPATH dup(?)
		db 	WMAXPATH dup(?)
		db 	WMAXPATH dup(?)
opfilter	S_FILT <-1,0,0,0,0,'*.*',0>
at_background	db 00h,10h,70h,70h,40h,30h,30h,70h
at_foreground	db 00h,0Ah,0Fh,0Bh,0Fh,07h,07h,07h
		db 08h,07h,00h,00h,0Fh,0Ah,0Fh,0Fh
at_palett	db 0,1,2,3,4,5,20,7
		db 56,57,58,59,60,61,62,63
pending_file	db WMAXPATH dup(?)

cpanel		dw offset spanela
panela		dw offset spanela
panelb		dw offset spanelb

DLG_Menusline	dd ?		; DOBJ
DLG_Statusline 	dd ?
DLG_Commandline	dd ?

copy_flag	db ?
copy_fast	db ?
copy_filecount	dw ?
copy_subdcount	dw ?

__srcfile	db 384 dup(?)
__srcpath 	db WMAXPATH dup(?)
__outfile 	db 384 dup(?)
__outpath 	db WMAXPATH dup(?)
entryname 	db 512 dup(?)
_bufin		label byte

default_ini label byte
ifdef __TE__
 incbin <doszip/default.ini>
else
 incbin <doszip/tiny.ini>
endif
ifdef __TV__
 incbin <tview/default.ini>
endif
ifdef __TE__
 incbin <tedit/default.ini>
endif
ifdef __DLL__
 incbin <plugins/default.ini>
endif
	db 0

cp_ercfgpath	db 'Error open config path: %s',10,10,0
cp_dz		db 'DZ',0
cp_temp		db 'TEMP',0
cp_path		db 'PATH',0
cp_ercomspec	db 'Error loading COMMAND.COM',10,0

cp_usage label byte
	db 'Command line switches',10
	db ' The following switches may be used in the command line:',10
	db 10
	db '  -T (tiny)  - read maximum 500 files in each panel',10
	db '  -L (large) - read maximum 5000 files in each panel',10
	db '     default is 3000.',10
	db 10
	db '  -XP (WinXP)     - trigger a mode change on startup', 10
	db '  -C<config_path> - Read/Write setup from/to <config_path>',10
	db 10
	db '  DZ <filename> command starts DZ and forces it to show <filename>',10
	db 'contents if it is an archive or show folder contents if <filename>',10
	db 'is a folder.',10,0
if ($ - _bufin) LE 1000h
	db 1000h - ($ - _bufin) dup(?)
endif
;------

pcellwb		dw 78 dup(0)
pcell_a		dw _D_BACKG or _D_MYBUF
		db 1,1, 2,2,12,1
		dd DGROUP:pcellwb
		db 2,2,12,1
pcell_b		dw _D_BACKG or _D_MYBUF
		db 1,1, 2,2,12,1
		dd DGROUP:pcellwb
		db 2,2,12,1
prect_a		dw _D_CLEAR or _D_COLOR
		dw 0
		db 0,1,40,20
		dd 0,0
prect_b		dw _D_CLEAR or _D_COLOR
		db 0,0,40,1,40,20
		dd 0,0
wspanela 	dw 0
wsmaxfba 	dw MAXFBLOCK
		dd DGROUP:path_a.wp_flag
		dd DGROUP:path_a.wp_mask
		dd DGROUP:path_a.wp_path
		dd DGROUP:path_a.wp_file
		dd DGROUP:path_a.wp_arch
		dd 0
wspanelb 	dw 0
wsmaxfbb 	dw MAXFBLOCK
		dd DGROUP:path_b.wp_flag
		dd DGROUP:path_b.wp_mask
		dd DGROUP:path_b.wp_path
		dd DGROUP:path_b.wp_file
		dd DGROUP:path_b.wp_arch
		dd 0
spanela		dw offset path_a
flaga		dw _P_PANELID or _P_MINISTATUS or _P_VISIBLE
		dw 0,0,0,0
		dd DGROUP:pcell_a
		dd DGROUP:prect_a
		dd DGROUP:wspanela
		dw 0
spanelb		dw offset path_b
flagb		dw _P_MINISTATUS or _P_VISIBLE
		dw 0,0,0,0
		dd DGROUP:pcell_b
		dd DGROUP:prect_b
		dd DGROUP:wspanelb
		dw 0
cp_load 	db 'Load',0
cp_exit 	db 'Exit',0
cp_comspec   	db 'Comspec',0
dz_comspec 	db 'COMMAND.COM',0
		db 80 - ($ - offset dz_comspec) dup(?)
cfgfile		db 'dz'
extini		db '.ini',0
extcfg		db '.cfg',0
extcmd		db '.cmd',0
configfile 	db MAXPATH dup(?)

ifdef __FAKEDZ__
dz_exe	S_DZDS <?>
	ASSUME cs:_DATA
dz_exec proc far
	mov	old_ds,ds
	mov	ax,cs
	mov	es,ax
	mov	ds,ax
	mov	old_si,si
	mov	old_di,di
	mov	di,offset dz_exe.dz_fcb_161
	mov	si,dz_exe.dz_exename
	mov	ax,2901h
	int	21h
	mov	bx,offset dz_exe.dz_envseg
	mov	dx,dz_exe.dz_exename
	mov	ax,4B00h
	int	21h
	mov	dx,cs
	mov	ds,dx
	jc	execute_error
	xor	ax,ax
    execute_error:
	mov	si,ax
	mov	ax,4D00h
	int	21h
	mov	dx,si
	mov	dz_exe.dz_eflag,dx
	mov	dz_exe.dz_errno,ax
	mov	si,old_si
	mov	di,old_di
	mov	ds,old_ds
	ret
dz_exec endp
	ASSUME cs:_DZIP
old_si	dw ?
old_di	dw ?
old_ds	dw ?
vector	label word
	dd 50495A44h
	dd DGROUP:dz_exe.dz_exeproc
	db 128 dup(?)
cp_exec	db 'Execute command:',10,'%s %s',0
endif

ifdef __DLL__

MAXPLUGINS	= 100

cp_dll		db 'dll',0	; subdirectory for plugins
cp_plugins	db 'Plugins',0	; ini section name
dllseg		dw ?		; memory adress of external binary
old_dll		dd ?		; saved vector F2
magic_table	label word	; file signatures
		dd MAXPLUGINS dup(?)
plugin_count	dw ?		; number of plugins defined in dz.ini

endif

ifdef __DLL__
	;
	; Doszip interrupt handler (F1)
	;
doszip_labels label word
	dw	doszip_dosmaperr	; 00: set errno
	dw	doszip_getsyserr	; 01: get system error message
	dw	doszip_malloc		; 02: allocate memory
	dw	doszip_free		; 03: free memory block
	dw	doszip_rsopen		; 04: open resourse
	dw	doszip_rsmodal		; 05: execute resourse
	dw	doszip_view		; 06: view file
	dw	doszip_edit		; 07: edit file
	dw	doszip_output		; 08: format output
	dw	doszip_command		; 09: command
	dw	doszip_inientryid	; 0A: Get string from DZ.INI
	dw	doszip_tmsgbox		; 0B: Message box
	dw	doszip_mklist		; 0C: Make list file
	dw	doszip_open		; 0D: Open file
	dw	doszip_close		; 0E: Close file
  if 0
	dw	doszip_getline		; 0F: getline dialog
	dw	doszip_dlinit		; 10: init dialog (= open resourse)
	dw	doszip_dlshow		; 11: show dialog
	dw	doszip_dlhide		; 12: hide dialog
	dw	doszip_dlevent		; 13: execute dialog
	dw	doszip_dlclose		; 14: close dialog
	dw	doszip_prg_open		; 15: open progress dialog
	dw	doszip_prg_close	; 16: close progress dialog
	dw	doszip_prg_set		; 17: set progress
	dw	doszip_prg_update	; 18: update progress
	dw	doszip_prg_size		; 19: get addr of &progress_size
	dw	doszip_filter_fblk	; 1A: filter(fblk)
	dw	doszip_filter_wblk	; 1B: filter(wfblk)
	dw	doszip_ogetouth 	; 1C: get out handle
	dw	doszip_confirmdf	; 1D: confirm delete file
	dw	doszip_confirmds	; 1E
	dw	doszip_preread		; 1F
	dw	doszip_predraw		; 20
	dw	doszip_cpanel_deselect	; 21
  endif
doszip_lcount = ($ - offset doszip_labels) / 2
doszip_label	dw ?
endif

ifdef DEBUG
_time_start	dd ?
	public	_time_start
format_files	db '__srcfile = %-30s',10
		db '__srcpath = %-30s',10
		db '__outfile = %-30s',10
		db '__outpath = %-30s',10
		db 'entryname = %-30s',10
		db 'wsub.arch = %-30s',10
		db 0
_DATA	ENDS

_DZIP	SEGMENT

	public	cmdebug

cmdebug	PROC	DIST
	mov	bx,cpanel
	mov	bx,word ptr [bx.pn_wsub]
	pushm	[bx.ws_arch]
	mov	ax,ds
	push	ax
	push	offset entryname
	push	ax
	push	offset __outpath
	push	ax
	push	offset __outfile
	push	ax
	push	offset __srcpath
	push	ax
	push	offset __srcfile
	mov	ax,offset format_files
	call	@ermsg
	add	sp,24
	ret
cmdebug	ENDP

else
_DATA	ENDS
_DZIP	SEGMENT
endif

getcfgfile proc
	invoke	setfext, addr configfile, addr extcfg
	ret
getcfgfile endp

getinifile proc
	invoke	setfext, addr configfile, addr extini
	ret
getinifile endp

getcmdfile proc
	invoke	setfext, addr configfile, addr extcmd
	ret
getcmdfile endp

ifdef __DLL__
	;
	; Doszip interrupt handler (F1)
	;
doszip: cmp	ah,doszip_lcount
	jae	doszip_notsup
	push	bx		; Clear carry flag (success)
	mov	bx,sp
	and	byte ptr [bx+6],not 1
	mov	bl,ah
	mov	bh,0
	add	bx,bx
	mov	bx,doszip_labels[bx]
	mov	doszip_label,bx
	pop	bx
	jmp	doszip_label
doszip_notsup:
	mov	ah,0
	push	bx		; Set carry flag (error)
	mov	bx,sp
	or	byte ptr [bx+6],1
	pop	bx
	iret
	;
	; Doszip interrupt functions (AH=XX)
	;
doszip_dosmaperr:			; 00
	invoke	dosmaperr, ax
	iret
doszip_getsyserr:			; 01
	push	bx
	mov	bx,errno
	shl	bx,2
	mov	ax,word ptr [bx+sys_errlist]
	mov	dx,word ptr [bx+sys_errlist+2]
	pop	bx
	iret
doszip_malloc:				; 02
	invoke	malloc, cx
	iret
doszip_free:				; 03
	invoke	free, dx::ax
	iret
doszip_rsopen:				; 04
	invoke	rsopen, dx::bx
	iret
doszip_rsmodal:				; 05
	invoke	rsmodal, dx::bx
	iret
doszip_view:				; 06
	invoke	tview, es::bx, dx::cx
	iret
doszip_edit:				; 07
	invoke	tedit, dx::bx, cx
	iret
doszip_output:				; 08
	invoke	_output, ss::cx, es::bx, ss::dx
	iret
doszip_command:				; 09
	push	di	; return 0 | error code
	mov	di,ax	; AL type
	push	dx	; 00 exit dzmain and call program
	push	bx	; 01 call inline
	call	command	; 02 hide screen
	or	ax,ax	; 04 trap stdout (plugins)
	jz	doszip_command_fail
	mov	dx,dzexitcode
	dec	ax
	test	di,1
	jz	doszip_command_end
	mov	mainswitch,ax
	mov	dzexitcode,ax
	test	di,2
	jz	doszip_command_do
	call	apihide
    doszip_command_do:
	les	bx,dzexe
	mov	es:[bx+214],bx
	mov	ax,bx
	add	ax,80
	mov	es:[bx-254],ax
	add	ax,220-80
	push	es
	push	ax
	mov	bx,sp
	call	dword ptr [bx]
	add	sp,4
    doszip_command_close:
	test	di,2
	jz	doszip_command_end
	call	apishow
    doszip_command_end:
	pop	di
	iret
    doszip_command_fail:
	mov	ax,ENOENT
	jmp	doszip_command_close
doszip_inientryid:			; 0A
	invoke	inientryid, dx::bx, cx
	iret
doszip_tmsgbox:				; 0B
	or	al,al
	mov	ax,_D_STDDLG
	jz	@F
	or	ax,_D_STDERR
    @@:
	invoke	tmsgbox, dx::bx, ax
	iret
doszip_mklist:				; 0C
	mov	mklist.mkl_unix,al
	mov	mklist.mkl_mask,dl
	call	mkziplst_open
	or	ax,ax
	mov	ax,ENOENT
	jz	@F
	call	mkziplst
	mov	cx,word ptr mklist.mkl_count
	mov	dx,word ptr mklist.mkl_count+2
    @@:
	iret
doszip_open:				; 0D
	push	dx	; DX:BX file name
	push	bx
	mov	ah,0	; AL attrib
	push	ax
	mov	al,ch	; CH mode
	push	ax
	mov	al,cl	; CL action
	push	ax
	call	osopen
	iret
doszip_close:				; 0E
	invoke	close, bx
	iret
if 0
doszip_getline:				; 0F
	invoke	tgetline, es::dx, ss::bx, ax, dx
	iret
doszip_dlinit:				; 10
	invoke	dlinit, dx::bx
	iret
doszip_dlshow:				; 11
	invoke	dlshow, dx::bx
	iret
doszip_dlhide:				; 12
	invoke	dlhide, dx::bx
	iret
doszip_dlevent:				; 13
	invoke	dlevent, dx::bx
	iret
doszip_dlclose:				; 14
	invoke	dlclose, dx::bx
	iret
doszip_prg_open:			; 15
	invoke	progress_open, dx::cx, es::bx
	iret
doszip_prg_close:			; 16
	call	progress_close
	iret
doszip_prg_set:				; 17
	invoke	progress_set, dx::cx, es::bx, si::di
	iret
doszip_prg_update:			; 18
	invoke	progress_update, dx::bx
	iret
doszip_prg_size:			; 19
	mov	ax,offset progress_size
	iret
doszip_filter_fblk:			; 1A
	invoke	filter_fblk, dx::bx
	iret
doszip_filter_wblk:			; 1B
	invoke	filter_wblk, dx::bx
	iret
doszip_ogetouth:			; 1C
	invoke	ogetouth, dx::bx
	iret
doszip_confirmdf:			; 1D
	invoke	confirm_delete_file, dx::bx, cx
	iret
doszip_confirmds:			; 1E
	invoke	confirm_delete_sub, dx::bx
	iret
doszip_preread:				; 1F
	mov	ax,bx
	call	panel_reread
	iret
doszip_predraw:				; 20
	mov	ax,bx
	call	panel_redraw
	iret
doszip_cpanel_deselect:			; 21
	invoke	cpanel_deselect, dx::bx
	iret
endif
	;
	; Install doszip handler
	;
install_doszip:
	push	cs
	pop	ds
	mov	dx,offset doszip
	mov	ax,2500h+DZ
	int	21h
	push	ss
	pop	ds
	ret
	;
	; Install dummy handler for DLL
	;
install_dummydll:
	push	cs
	pop	ds
	mov	dx,offset doszip_notsup
	mov	ax,2500h+DLL
	int	21h
	push	ss
	pop	ds
	ret
	;
	; Read file signatures from DZ.INI
	;
readplugins:
	push si
	sub si,si
	.repeat
	    invoke inientryid, addr cp_plugins, plugin_count
	    .break .if !ax
	    add	ax,2
	    invoke xtol, dx::ax
	    stom magic_table[si]
	    add si,4
	    inc plugin_count
	.until 0
	pop si
	ret
	;
	; Find plugin from signature in DX:AX
	;
findplugin proc
	push	si
	sub	si,si
	mov	bx,si
    findplugin_loop:
	cmp	si,plugin_count
	jae	findplugin_break
	cmp	ax,magic_table[bx]
	jne	findplugin_next
	mov	cx,magic_table[bx+2]
	test	cl,cl
	jz	@F
	cmp	cl,dl
	jne	findplugin_next
      @@:
	test	ch,ch
	jz	@F
	cmp	ch,dh
	jne	findplugin_next
;	.if !cl || (cl == dl && (!ch || ch == dh))
      @@:
	mov	cx,si
	inc	si
	jmp	findplugin_end
    findplugin_next:
	inc	si
	add	bx,4
	jmp	findplugin_loop
    findplugin_break:
	sub	ax,ax
    findplugin_end:
	pop	si ; return ZF clear -- CX index in [Plugins]
	ret
findplugin endp
	;
	; Find plugin in [Filetype] from <filename>
	;
finddlltype proc
	invoke strrchr, dx::ax, '.'
	.if ax
	    inc ax
	    invoke inientry, addr cp_initype, dx::ax, addr configfile
	    .if ax
		mov bx,ax
		mov al,[bx]
		.if al == '['
		    add bx,3
		    invoke xtol, dx::bx
		    or cl,1
		    ret
		.endif
	    .endif
	.endif
	xor ax,ax
	ret
finddlltype endp
	;
	; Get .dll file name from DZ.INI. CX index
	;
get_dllfile proc
	push si
	invoke inientryid, addr cp_plugins, cx
	.if ax
	    invoke strchr, dx::ax, ','
	    .if ax
		inc ax
		mov si,ax
		lodsb
		.while al == ' ' || al == 9
		    lodsb
		.endw
		mov ax,si
		dec ax
	    .endif
	.endif
	pop si
	ret
get_dllfile endp
	;
	; Unload plugin
	;
freeplugin proc
	mov	ax,dllseg
	test	ax,ax
	jz	@F
	dec	ax
	push	ax
	push	ax
	mov	ah,_DLL_EXIT
	int	DLL
	call	free
	sub	ax,ax
	mov	dllseg,ax
	call	install_dummydll
      @@:
	ret
freeplugin endp
	;
	; Load plugin from [Plugins] or [Filetype]
	;
loadplugin proc pascal uses si di magic:dword, archive:dword
local filename[WMAXPATH]:byte
	call	freeplugin
	lodm	archive
	call	finddlltype
	test	ax,ax
	jnz	@F
	lodm	magic	; [Filetype] redefines magic
      @@:
	stom	magic
	call	findplugin
	jnz	@F
	jmp	loadplugin_end
      @@:
	call	get_dllfile
	test	ax,ax
	jnz	@F
	jmp	loadplugin_nil
      @@:
	mov	si,ax
	cmp	byte ptr [si+1],':'
	je	@F
	invoke	strfcat, addr filename, addr configpath, addr cp_dll
	invoke	strfcat, dx::ax, 0, dx::si
      @@:
	invoke	osopen, dx::ax, _A_NORMAL, M_RDONLY, A_OPEN
	mov	si,ax
	cmp	ax,-1
	jne	@F
	jmp	loadplugin_nil
      @@:
	mov	bx,ax
	mov	ax,4202h	; get size of binary
	xor	cx,cx
	xor	dx,dx
	int	21h
	jnc	@F
	jmp	loadplugin_close
      @@:
	test	dx,dx
	jz	@F
	jmp	loadplugin_close
      @@:
	add	ax,16
	jnc	@F
	jmp	loadplugin_close
      @@:
	invoke	malloc,ax
	jnz	@F
	jmp	loadplugin_close
      @@:
	inc	dx		; make zero offset
	mov	dllseg,dx
	mov	bx,si
	mov	ax,4200h	; seek back and read file
	xor	cx,cx
	xor	dx,dx
	int	21h
	mov	cx,ax
	dec	cx
	mov	dx,dllseg
	invoke	osread, si, dx::ax, cx
	xchg	ax,si
	invoke	close,ax
	test	si,si
	jz	@F
	mov	ax,dllseg
	mov	es,ax
	xor	bx,bx
	mov	ax,es:[bx+2]
	cmp	word ptr es:[bx],5A44h
	jne	@F
	cmp	ax,VERSION
	ja	@F
	cmp	ax,MINVERS
	jb	@F
	push	ds	; install vector
	mov	ax,dllseg
	mov	ds,ax
	mov	dx,100h	; interrupt offset in binary
	mov	ax,2500h+DLL
	int	21h
	pop	ds
  ifdef __MOUSE__
	call	mouseget
	mov	dh,ah
  else
	xor	dx,dx
	mov	al,dl
  endif
	mov	ax,offset _dsstack
  ifdef __TE__
	add	ax,SIZE S_TEDIT + 16
  endif
	mov	es,ax
	mov	cx,_scrseg
	mov	bh,_scrrow
	mov	bl,_scrcol
	mov	di,word ptr magic
	mov	si,word ptr magic+2
	mov	ah,_DLL_LOAD
	int	DLL
	jc	@F
	xor	ax,ax
	inc	ax
	jmp	loadplugin_end
      @@:
	call	freeplugin
	jmp	loadplugin_nil
    loadplugin_close:
	invoke	close, si
    loadplugin_nil:
	xor	ax,ax
    loadplugin_end:
	ret
loadplugin endp

loadpaneldll proc pascal uses si
local	arcname[WMAXPATH]:byte
	mov si,offset path_a
	.if [si.wp_flag] & _W_ARCHEXT || path_b.wp_flag & _W_ARCHEXT
	    invoke strfcat, addr arcname, addr [si.wp_path], addr [si.wp_file]
	    invoke readword, dx::ax
	    invoke loadplugin, dx::ax, addr arcname
	    .if !ax
		and [si.wp_flag],not _W_ARCHEXT
	    .endif
	.endif
	ret
loadpaneldll endp

endif

ioupdate proc DIST pascal stream:BYTE
	lodm STDO.ios_total
	.if !stream
	    lodm STDI.ios_total
	.endif
	invoke progress_update, dx::ax
	.if ax
	    xor ax,ax	; User break (ESC)
	.else
	    mov ax,1
	.endif
	ret
ioupdate endp

cmp_envstring proc
	push di
    	.repeat
	    mov ah,es:[di]
	    lodsb
	    inc di
	    or ax,2020h
	.until al != ah
	or al,ah
	cmp al,'='
	pop di
	ret
cmp_envstring endp

cmp_environ proc
	mov si,offset cp_dz
	call cmp_envstring
	jnz cmp_temp
	mov si,offset envconf
	mov ax,3
	jmp cmp_found
    cmp_temp:
	mov si,offset cp_temp
	call cmp_envstring
	jnz cmp_path
	mov si,offset envtemp
	mov ax,5
	jmp cmp_found
    cmp_path:
	mov si,offset cp_path
	call cmp_envstring
	jnz cmp_comspec
	mov si,offset envpath
	mov ax,5
	jmp cmp_found
    cmp_comspec:
	mov si,offset cp_comspec
	call cmp_envstring
	jnz cmp_end
	mov si,offset comspec
	mov ax,8
    cmp_found:
	add ax,di
	mov [si],ax
	mov [si+2],es
    cmp_end:
	ret
cmp_environ endp

get_environ proc
	mov ax,envseg
	mov es,ax
	xor di,di
	mov cx,7FFFh
	cld
	.repeat
	    call cmp_environ
	    sub ax,ax
	    repnz scasb
	.until es:[di] == al
	.if word ptr envtemp == ax
	    mov ax,offset programpath
	    mov word ptr envtemp,ax
	    mov word ptr envtemp+2,ds
	.endif
	ret
get_environ endp

init_args proc
	mov si,ax
    args_loop:
	mov bx,si
	shl bx,2
	add bx,_argv
	mov bx,[bx]
	mov al,[bx]
	cmp al,'?'
	je  arg_?
	cmp al,'/'
	je  arg_x
	cmp al,'-'
	je  arg_x
	mov argvfile,bx
	jmp next_arg
    arg_x:
	inc bx
	mov al,[bx]
	or  al,20h
	cmp al,'x'
	jne arg_t
	mov ax,dzcount
	or ax,ax
	jnz next_arg
	mov ax,0003h
	int 10h
	call _screct
	jmp next_arg
    arg_t:
	cmp al,'t'
	jne arg_l
	mov numfblock,500
	jmp next_arg
    arg_l:
	cmp al,'l'
	jne arg_c
	mov numfblock,5000
	jmp next_arg
    arg_c:
	cmp al,'c'
	jne arg_?
	inc bx
	push es
	push bx
	invoke filexist, es::bx
	cmp ax,2
	pop ax
	pop dx
	jne arg_?
	invoke strcpy, addr configpath, dx::ax
	jmp next_arg
    arg_?:
	mov ax,offset cp_usage
	call @printf
	push 0
	call exit
    next_arg:
	inc si
	cmp si,_argc
	jae end_args
	jmp args_loop
    end_args:
	ret
init_args endp

copy_axdi proc
	invoke strcpy, ds::ax, ds::di
	sub ax,ax
	ret
copy_axdi endp

test_path proc
	mov	ax,[si]
	or	al,al
	jz	test_path_02
	cmp	al,'\'
	je	test_path_03
	cmp	ah,':'
	jne	test_path_02
	and	al,not 20h
	sub	al,'A'
	mov	ah,0
	push	ax
	call	_disk_type
	or	ax,ax
	jz	test_path_02
    test_path_00:
	mov	al,[si]
	call	@drvexist
	jz	test_path_01
	push	ds
	push	si
	call	filexist
	or	ax,ax
	jnz	test_path_03
	push	ds
	push	si
	push	'\'
	call	strrchr
	jz	test_path_01
	mov	bx,ax
	mov	ax,3A00h
	cmp     [bx-1],ah
	je	test_path_01
	mov	[bx],al
	cmp	sys_erflag,al
	je	test_path_00
    test_path_01:
	call	trace
    test_path_02:
    	mov ax,si
	call copy_axdi
	ret
    test_path_03:
	xor	ax,ax
	inc	ax
	ret
test_path endp

init_panels proc
	movmw spanela.pn_flag,config.c_flaga
	movmw spanelb.pn_flag,config.c_flagb
	movmm spanela.pn_fcb_index,config.c_fcb_indexa
	movmm spanelb.pn_fcb_index,config.c_fcb_indexb
	sub ax,ax
	mov di,offset cp_stdmask
	.if path_a.wp_mask == al
	    mov ax,offset path_a.wp_mask
	    call copy_axdi
	.endif
	.if path_b.wp_mask == al
	    mov ax,offset path_b.wp_mask
	    call copy_axdi
	.endif
      ifdef __LFN__
	.if !(console & CON_IOLFN)
	    mov _ifsmgr,al
	.endif
	.if _ifsmgr == al
	    and path_a.wp_flag,not _W_LONGNAME
	    and path_b.wp_flag,not _W_LONGNAME
	.endif
      endif
	mov dx,argvfile
	.if dzcount == ax && dx != ax
	    .if !func(access, ds::dx, ax)
		.if cx & _A_SUBDIR
		  @@:
		    and cflag,not _C_PANELID
		    mov bx,argvfile
		    mov dx,':'
		    .if [bx+1] == dl
		    	mov dl,[bx]
			or  dl,20h
		    	sub dl,'a'
		    	mov ah,0Eh
		    	int 21h
		    .endif
		    push ds
		    push argvfile
		    call chdir
		    jmp @F
		.else
		    invoke readword, argvfile
		    .if ax == 4B50h
			and path_a.wp_flag,not (_W_ARCHIVE or _W_ROOTDIR)
			and path_b.wp_flag,not (_W_ARCHIVE or _W_ROOTDIR)
			or path_a.wp_flag,_W_ARCHZIP
			or flaga,_P_VISIBLE
			mov path_a.wp_arch,0
			invoke strfn, argvfile
			push dx
			push ax
			invoke strcpy, addr path_a.wp_file, dx::ax
			pop ax
			pop dx
			.if ax != argvfile
			    mov es,dx
			    dec ax
			    mov bx,ax
			    xor al,al
			    mov es:[bx],al
			    jmp @B
			.endif
		      @@:
			and cflag,not _C_PANELID
			invoke fullpath, addr path_a.wp_path, 0
		    .else
		    	sub ax,ax
		    .endif
		.endif
	    .endif
	.endif
	ret
init_panels endp

dzmainexit proc
	mov ax,offset cp_dznotloaded
	call @printf
	push 0
	call exit
dzmainexit endp

ifdef __INI_LOAD__

dzloadexit proc
	push bp
	mov bp,ax
	mov di,offset _dsstack + 2048
	xor si,si
	mov [di],si
	.repeat
	    .break .if !func(inientryid, ss::bp, si)
	    inc si
	    invoke strcat, dx::di, dx::ax
	    invoke strcat, dx::ax, addr CRLF$
	.until 0
	test si,si
	pop bp
	ret
dzloadexit endp

endif

create_DZ_INI proc
	push si
	invoke osopen, dx::ax, _A_NORMAL, M_WRONLY, A_CREATE or A_TRUNC
	mov si,ax
	.if ax != -1
	    or _osfile[si],FH_TEXT
	    invoke strlen, addr default_ini
	    invoke write, si, addr default_ini, ax
	    invoke close, si
	    mov ax,1
	.endif
    	pop si
	ret
create_DZ_INI endp

dzmain	proc DIST
	mov al,_ifsmgr
	mov ifsmgr,al
	call get_environ
	call menusinit_OIDD
  ifdef __FAKEDZ__
	mov word ptr dzexe,offset vector
	mov word ptr dzexe+2,ds
	mov ax,envseg
	mov dz_exe.dz_envseg,ax
	mov ax,ds
	mov dz_exe.dz_command[2],ax
	mov dz_exe.dz_fcb_0P[2],ax
	mov dz_exe.dz_fcb_1P[2],ax
	mov dz_exe.dz_exename,offset dz_exe.dz_exeproc
	mov dz_exe.dz_command,offset dz_exe.dz_execommand
	mov dz_exe.dz_fcb_0P,offset dz_exe.dz_fcb_160
	mov dz_exe.dz_fcb_1P,offset dz_exe.dz_fcb_161
	push ds
	push offset dz_exe.dz_dzmain
	mov bx,_argv
	push ds
	push word ptr [bx]
	call strcpy
	mov di,offset dz_exe.dz_fcb_160
	mov si,ax
	mov ax,2901h
	int 21h
  endif
	les bx,dzexe
  ifndef __FAKEDZ__
	add bx,03C4h
	les bx,es:[bx]
  endif
	mov si,es:[bx]
	mov di,es:[bx+2]
	mov ax,es:[bx+6]
	mov bx,es:[bx+4]
	mov es,ax
	cmp di,5049h
	jne dzmainexit
	cmp si,5A44h
	jne dzmainexit
	mov word ptr dzexe,bx
	mov word ptr dzexe+2,es
	add bx,208
	mov ax,es:[bx]
	mov dzerrno,ax
	mov ax,es:[bx+2]
	mov dzerflag,ax
	mov ax,es:[bx+4]
	mov dzcount,ax
  ifdef __DLL__
	mov ax,3500h+DLL
	int 21h
	mov word ptr old_dll,bx
	mov word ptr old_dll+2,es
	call install_doszip
	call install_dummydll
  endif
	;
	; Set program path (%doszip%) and config path (%dz%):
	;	(1) from program path
	;	(2) from environ %DZ%
	;	(3) from command line /C<path>
	;
	mov bx,_argv
	mov bx,[bx]
	invoke strcpy, addr programpath, ss::bx
	invoke strpath, dx::ax
	invoke strcpy, addr configpath, dx::ax
	sub ax,ax			; Test environ (%DZ%) config path
	.if word ptr envconf != ax
	    invoke filexist, envconf
	    .if ax == 2			; directory ?
		invoke strcpy, addr configpath, envconf
	    .else
		pushm envconf		; Warning: missing config path
		mov ax,offset cp_ercfgpath
		call @printf
		add sp,4
	    .endif
	.endif
	mov ax,1
	.if ax < _argc
	    call init_args		; the option /C<path> overrides %DZ%
	.endif
	invoke strfcat, addr configfile, addr configpath, addr cfgfile
	call config_read		; Read DZ.CFG
	.if !word ptr comspec
	    mov ax,offset cp_ercomspec
	    call @printf
	.endif
	lodm comspec
	.if ax
	    invoke strcpy, addr dz_comspec, dx::ax
	    stom comspec	; Use default -- this will fail..
	.endif
	call getinifile
	.if !func(filexist, dx::ax)	; DZ.INI exist ?
	    call getinifile
	    call create_DZ_INI		; virgin call..
	    mov config.c_cel_indexa,5
	.endif
	.if func(inientryid, addr cp_comspec, 0)
	    push dx
	    push ax
	    invoke expand_environ, dx::ax
	    invoke filexist, dx::ax
	    pop ax
	    pop dx
	    .if !ZERO?
		invoke strncpy, addr dz_comspec, dx::ax, 80
		mov comargs,0
		.if func(inientryid, addr cp_comspec, 1)
		    invoke expand_environ, dx::ax
		    invoke strncpy, addr comargs, dx::ax, 64
		.endif
	    .endif
	.endif
	LPUSH cs
	push offset cmhelp
	call thelpinit
	LMOV ax,cs
	LMOV word ptr oupdate+2,ax
	mov word ptr oupdate,offset ioupdate
	mov ax,numfblock
	mov wsmaxfbb,ax
	mov wsmaxfba,ax
	call setconfirmflag
	mov bx,offset pending_file
	.if byte ptr [bx]
	    invoke removefile, ds::bx
	    mov pending_file,0
	.endif
	.if cflag & _C_DELTEMP
	    invoke removetemp, addr cp_ziplst
	    invoke removetemp, addr cp_dzcmd
	.endif
	and cflag,not _C_DELTEMP
  ifdef __INI_LOAD__
	cmp dzcount,0
	jne @F
	mov ax,offset cp_load
	call dzloadexit
	jz @F
	invoke command, ss::di
	or ax,ax
	jz @F
	mov ax,23
   ifndef DEBUG
	ret
   endif
    @@:
  endif
	call init_panels
	call apiopen
	call cursoroff
  ifdef __MOUSE__
	.if console & CON_MOUSE
	    call mouseinit
	    call mouseon
	.endif
  endif
	call history_open
	call getinifile
  ifdef __DLL__
	call readplugins
	call loadpaneldll
  endif
	call prect_open_ab
	mov ax,offset spanelb
	.if cpanel == ax
	    mov ax,offset spanela
	.endif
	call panel_openmsg
	mov di,offset programpath
	mov si,offset path_a.wp_path
	call test_path
	.if ZERO?
	    and path_a,not _W_ARCHIVE
	.endif
	mov si,offset path_b.wp_path
	call test_path
	.if ZERO?
	    and path_b,not _W_ARCHIVE
	.endif
	.if cflag & _C_COMMANDLINE
	    call cursoron
	.endif
	call panel_open_ab
	or ax,ax
	jz dzmain_14
  ifdef __FAKEDZ__
    dzmain_debug:
	call dzmodal
	cmp dzexitcode,23
	jne dzmain_14
	mov dzexitcode,0
	mov mainswitch,0
	lodm dzexe
	add ax,82
	push dx
	push ax
	push dx
	sub ax,82
	push ax
	mov ax,offset dz_comspec
	mov dx,offset cp_exec
	call @stdmsg
	add sp,8
	jmp dzmain_debug
  else
	call dzmodal
  endif
    dzmain_14:
	movmw config.c_fcb_indexa,spanela.pn_fcb_index
	movmw config.c_cel_indexa,spanela.pn_cel_index
	movmw config.c_fcb_indexb,spanelb.pn_fcb_index
	movmw config.c_cel_indexb,spanelb.pn_cel_index
	mov bx,word ptr spanela.pn_dialog
	mov ax,spanela.pn_flag
	and ax,not _P_VISIBLE
	.if [bx.dl_flag] & _D_DOPEN
	    or ax,_P_VISIBLE
	.endif
	mov config.c_flaga,ax
	mov bx,word ptr spanelb.pn_dialog
	mov ax,spanelb.pn_flag
	and ax,not _P_VISIBLE
	.if [bx.dl_flag] & _D_DOPEN
	    or ax,_P_VISIBLE
	.endif
	mov config.c_flagb,ax
	.if cflag & _C_AUTOSAVE
	    call config_save
	.endif
	mov ax,panela
	call panel_close
	mov ax,panelb
	call panel_close
	call apiclose
	push 0
	push com_info.ti_ypos
	call gotoxy
	call history_close
  ifdef __TE__
	call tcloseall
  endif
	cmp dzexitcode,23
	je dzmain_16
	test cflag,_C_SAVEHISTORY
	jnz dzmain_16
	call history_delete
    dzmain_16:
  ifdef __DLL__
   ifdef __INI_LOAD__
	cmp dzexitcode,23
	je dzmain_17
	call getinifile
	mov ax,offset cp_exit
	call dzloadexit
	jz dzmain_17
	push dzexitcode
	mov dx,ss
	mov bx,di
	mov ah,_DZ_command
	mov al,SPAWN_INLINE
	int DZ
	invoke removetemp, addr cp_dzcmd
	pop ax
	mov dzexitcode,ax
    dzmain_17:
   endif
	push ds
	lds dx,old_dll
	mov ax,2500h+DLL
	int 21h
	pop ds
  endif
	mov ax,dzexitcode
	ret
dzmain	endp

_DZIP	ENDS

	END
