include clib.inc

ifdef __ZIP__

include wsub.inc
include dos.inc
include dir.inc
include fblk.inc
include string.inc
include io.inc
include iost.inc
include unzip.inc
include filter.inc
include progress.inc
include malloc.inc
include conio.inc
include syserrls.inc
include doserrls.inc
include errno.inc
include format.inc

	public	cp_emarchive

DC_MAXOBJ = 5000 ; Max number of files in one subdir (recursive)

_TEXT	SEGMENT

wzipfindentry proc dist pascal public uses si di fblk:dword, ziph:word
	mov si,ziph
	les di,fblk
	invoke strlen, addr es:[di.fb_name]
	add ax,SIZE S_FBLK
	add di,ax
	invoke lseek, si, es:[di], SEEK_SET
	invoke osread, si, addr zip_local, SIZE S_LZIP
	.if ax == SIZE S_LZIP && zip_local.lz_pkzip == ZIPHEADERID && \
	    zip_local.lz_zipid == ZIPLOCALID
	    mov ax,zip_local.lz_fnsize
	    add ax,zip_local.lz_extsize
	    invoke lseek, si, ax, SEEK_CUR
	    .if zip_local.lz_flag & 8
		les ax,[bp+6]
		mov ax,es:[di+4]
		mov word ptr zip_local.lz_crc,ax
		mov ax,es:[di+6]
		mov word ptr zip_local.lz_crc+2,ax
		mov ax,es:[di+8]
		mov word ptr zip_local.lz_csize,ax
		mov ax,es:[di+10]
		mov word ptr zip_local.lz_csize+2,ax
	    .endif
	    mov ax,1
	.else
	    sub ax,ax
	.endif
	test ax,ax
	ret
wzipfindentry endp

wzipcopyfile proc dist pascal public uses si di wsub:dword, fblk:dword, out_path:dword
local	fhandle:word
local	fname[WMAXPATH]:byte
	invoke	filter_fblk, fblk
	test	ax,ax
	jz	wzipcopyfile_end	; 0 == jump
	invoke	wsopenarch, wsub
	mov	si,ax
	inc	ax
	jz	wzipcopyfile_nozip	; -1 == error open
	invoke	wzipfindentry, fblk, si
	jz	wzipcopyfile_nofile	; 0 -> ER_FIND = 11
	lea	di,fname
	les	bx,fblk
	invoke	strfcat, ss::di, out_path, addr es:[bx.fb_name]
	les	bx,fblk
	invoke	progress_set, addr es:[bx.fb_name], out_path, es:[bx.fb_size]
	jnz	wzipcopyfile_exit	; 66 == ER_USERABORT
	invoke	ogetouth, ss::di
	cmp	ax,-1
	je	wzipcopyfile_exit	; -1 == error create
	test	ax,ax
	jz	wzipcopyfile_exit	; 0 == jump
	mov	fhandle,ax  		; unzip_handle(AX,DX);
	mov	dx,ax
	les	bx,fblk
	mov	ax,es:[bx]
	mov	zip_attrib,ax
	mov	ax,si
	call	unzip
	push	ax
	invoke	close, si
	pop	ax
	test	ax,ax
	les	bx,fblk
	jnz	wzipcopyfile_remove
  ifdef __LFN__
	cmp	_ifsmgr,al
	jne	wzipcopyfile_ifs
  endif
	invoke	setfdate, fhandle, es:[bx.fb_date], es:[bx.fb_time]
	invoke	close, fhandle
  ifdef __LFN__
	jmp	wzipcopyfile_flag
    wzipcopyfile_ifs:
	invoke	close, fhandle
	les	bx,fblk
	invoke	wsetwrdate, ss::di, es:[bx.fb_date], es:[bx.fb_time]
    wzipcopyfile_flag:
  endif
	les	bx,fblk
	mov	ax,es:[bx]
	and	ax,_A_FATTRIB
	invoke	setfattr, ss::di, ax
	xor	ax,ax
    wzipcopyfile_end:
	ret
    wzipcopyfile_nozip:
	mov	ax,ER_NOZIP
	jmp	wzipcopyfile_end
    wzipcopyfile_nofile:
	push	word ptr fblk+2
	mov	ax,word ptr fblk
	add	ax,fb_name
	push	ax
	mov	dx,offset format_s
	mov	ax,offset CP_ENOENT
	call	@ermsgt
	add	sp,4
	mov	ax,ER_FIND
    wzipcopyfile_exit:
	push	ax
	invoke	close, si
	pop	ax
	jmp	wzipcopyfile_end
    wzipcopyfile_remove:
	mov	si,fhandle
	push	ss
	push	di
	mov	di,ax
	call	remove
	mov	ax,di
	cmp	ax,ER_USERABORT
	je	wzipcopyfile_exit
	cmp	ax,ER_MEM
	je	wzipcopyfile_ermem
	cmp	ax,ER_DISK
	je	wzipcopyfile_erdisk
	mov	dx,offset CP_DOSER04
	mov	ax,offset cp_emarchive
	jmp	wzipcopyfile_ermsgt
    wzipcopyfile_ermem:
	mov	ax,offset CP_ENOMEM
	jmp	wzipcopyfile_ermsgt
    wzipcopyfile_erdisk:
	mov	dx,offset CP_ENOMEM
	mov	ax,offset CP_DOSER20
    wzipcopyfile_ermsgt:
	call	@ermsgt
	mov	ax,di
	jmp	wzipcopyfile_exit
wzipcopyfile endp

wzipcopypath proc dist pascal public uses si di wsub:dword, fblk:dword, out_path:dword
local	SBUF[38]:byte
	lea	di,[bp-36]
	les	bx,wsub
	xchg	di,bp
	movmx	[bp.ws_path],es:[bx.ws_path]
	movmx	[bp.ws_file],es:[bx.ws_file]
	movmx	[bp.ws_mask],es:[bx.ws_mask]
	mov	si,offset scan_fblock
	mov	[si.wp_flag],_W_SORTSIZE
	mov	ax,si
	mov	word ptr [bp.ws_flag],ax
	mov	word ptr [bp.ws_flag+2],ds
	add	ax,wp_arch
	mov	word ptr [bp.ws_arch],ax
	mov	word ptr [bp.ws_arch+2],ds
	mov	[bp.ws_count],0
	mov	[bp.ws_maxfb],DC_MAXOBJ
	xchg	di,bp
	push	ds
	push	ax
	mov	dx,word ptr fblk+2
	mov	ax,word ptr fblk
	add	ax,fb_name
	les	bx,es:[bx.ws_arch]
	cmp	byte ptr es:[bx],0
	je	wzipcopypath_cpy
	push	es
	push	bx
	push	dx
	push	ax
	call	strfcat
	jmp	wzipcopypath_dir
    wzipcopypath_cpy:
	push	dx
	push	ax
	call	strcpy
    wzipcopypath_dir:
	add	si,wp_file
	les	bx,fblk
	invoke	strfcat, ds::si, out_path, addr es:[bx.fb_name]
	invoke	mkdir, ds::si
	cmp	ax,-1
	je	wzipcopypath_wsub
	invoke	setfattr, ds::si, 0
	test	ax,ax
	jnz	wzipcopypath_wsub
	les	bx,fblk
	mov	ax,es:[bx]
	and	ax,_A_FATTRIB
	and	ax,not _A_SUBDIR
	invoke	setfattr, ds::si, ax
    wzipcopypath_wsub:
	push	ds
	push	si
	add	si,WMAXPATH
	invoke	strlen, ds::si
	add	ax,si
	mov	[bp-6],ax
	call	strlen
	sub	si,WMAXPATH
	add	ax,si
	mov	[bp-4],ax
	les	bx,fblk
	invoke	progress_set, addr es:[bx.fb_name], out_path, 0
	jnz	wzipcopypath_end
	invoke	wsopen, ss::di
	test	ax,ax
	jnz	wzipcopypath_read
	dec	ax
	jmp	wzipcopypath_end
    wzipcopypath_read:
	invoke	wzipread, ss::di
	cmp	ax,1
	ja	wzipcopypath_sort
	invoke	wsclose, ss::di
	xor	ax,ax
    wzipcopypath_end:
	ret
    wzipcopypath_warning:
	push	ax
	push	ax
	mov	ax,offset cp_warning
	mov	dx,offset cp_emaxfb
	call	@stdmsg
	add	sp,4
	jmp	wzipcopypath_max
    wzipcopypath_sort:
	invoke	wssort, ss::di
	mov	ax,[di.ws_maxfb]
	cmp	ax,[di.ws_count]
	je	wzipcopypath_warning
    wzipcopypath_max:
	mov	ax,[di.ws_count]
	dec	ax
	mov	[bp-2],ax
	xor	ax,ax
	mov	[bp-38],ax
    wzipcopypath_next:
	cmp	byte ptr [bp-38],0
	jnz	wzipcopypath_close
	mov	ax,[bp-2]
	cmp	ax,1
	jl	wzipcopypath_close
	les	bx,[di.ws_fcb]
	shl	ax,2
	add	bx,ax
	mov	dx,es:[bx+2]
	mov	bx,es:[bx]
	mov	es,dx
	mov	ax,es:[bx]
	and	ax,_A_SUBDIR
	jz	wzipcopypath_file
	invoke	wzipcopypath, ss::di, dx::bx, ds::si
	mov	[bp-38],ax
	xor	al,al
	mov	bx,[bp-6]
	mov	[bx],al		; *a = 0;
	mov	bx,[bp-4]
	mov	[bx],al		; *p = 0;
	jmp	wzipcopypath_free
    wzipcopypath_close:
	invoke	wsclose, ss::di
	mov	ax,[bp-38]
	jmp	wzipcopypath_end
    wzipcopypath_file:
	push	dx
	push	bx
	invoke	progress_set, addr es:[bx.fb_name], out_path, es:[bx.fb_size]
	mov	[bp-38],ax
	pop	bx
	pop	dx
	jnz	wzipcopypath_close
	invoke	wzipcopyfile, ss::di, dx::bx, ds::si
	mov	[bp-38],ax
    wzipcopypath_free:
	les	bx,[di.ws_fcb]
	mov	ax,[bp-2]
	shl	ax,2
	add	bx,ax
	xor	ax,ax
	pushm	es:[bx]
	mov     es:[bx],ax
	mov     es:[bx+2],ax
	call	free
	dec	word ptr [bp-2]
	jmp	wzipcopypath_next
wzipcopypath endp

wzipcopy proc dist pascal public wsub:dword, fblk:dword, out_path:dword
	les bx,fblk
	pushm wsub
	push es
	push bx
	pushm out_path
	.if byte ptr es:[bx] & _A_SUBDIR
	    call wzipcopypath
	.else
	    call wzipcopyfile
	.endif
	ret
wzipcopy endp

_TEXT	ENDS

_DATA	SEGMENT

cp_emarchive db	'Error in archive',0

_DATA	ENDS

endif

	END
