; DZARJ.ASM--
; Copyright (c) 2011 Hjort Nidudsson
;
	.model	tiny
	.code
	.286

DLLVER	equ	0102h		; version
VERS?	equ	<'1.02'>
PROC?	equ	111101111B	; functions included
FLAG?	equ	111101110B	; functions that need ARJ.EXE
NAME?	equ	<'ARJ'>
TYPE?	equ	<'.arj'>

;DEBUG	equ 	1

include	inc/dll.inc

DLL_Header	PROC?, FLAG?, DLLVER
DLL_Startup	PROC?, FLAG?

include	inc/io.inc
include	inc/string.inc
include	inc/stdlib.inc
include	inc/wsub.inc
include	inc/assert.inc


c_entry	db	NAME?,0		; the [<entry>] in dz.ini to read from

ARG_02	db	'arj x -y',0	; 02 - Copy - e if not include subdir
ARG_03	db	'arj a -y',0	; 03 - Add
ARG_04	db	'arj m -y',0	; 04 - Move
ARG_06	db	'arj d -p -y',0	; 06 - Delete
ARG_07	db	'arj n',0	; 07 - Rename
ARG_08	db	'arj m -e -y',0 ; 08 - Edit
ARG_09	db	'arj e -y',0	; 09 - View - or copy single file (02)

CPF_02	db	' %s %s\',0	; <archive> -o<outpath>
CPF_03	db	' %s',0     	; <archive>
CPTEMP	db	' !%%TEMP%%\ziplst',0

CMD_00	db 	64 dup(?)
CMD_02	db 	64 dup(?)	; buffer for command format string
CMD_03	db 	64 dup(?)
CMD_04	db 	64 dup(?)
CMD_06	db 	64 dup(?)
CMD_07	db 	64 dup(?)
CMD_08	db 	64 dup(?)
CMD_09	db	64 dup(?)

config_label label word		; table: <default value>, <buffer>
	dw	offset ARG_09, offset CMD_00
	dw	0,0
	dw	offset ARG_02, offset CMD_02
	dw	offset ARG_03, offset CMD_03
	dw	offset ARG_04, offset CMD_04
	dw	0,0
	dw	offset ARG_06, offset CMD_06
	dw	offset ARG_07, offset CMD_07
	dw	offset ARG_08, offset CMD_08
	dw	offset ARG_09, offset CMD_09

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

include	inc/wsub.asm
include	inc/stdlib.asm
include	inc/string.asm
include	inc/dll.asm
include	inc/stdio.asm
include	inc/dos.asm
include	inc/dir.asm
include	inc/mouse.asm

;-------------------------------------------------------------------------
; Function 00 - Init
;-------------------------------------------------------------------------

dll_init:
	invoke	searchp, addr CString("ARJ.EXE")
	or	ax,ax
	jz	dll_init_clear	; clear functions needing ARJ.EXE
	call	init_args
	xor	ax,ax
	iret
    dll_init_clear:
	xor	cs:$FLAG,FLAG?
	iret

init_args:      		; Compile arguments to CMD
	mov	cx,_DLL_COPY
	call	init_args_find	; try DZ.INI or use default
	invoke	strcat, dx::ax, addr cs:CPF_02
	invoke	strcat, dx::ax, addr cs:CPTEMP
	mov	cx,0
	call	init_args_find
	invoke	strcat, dx::ax, addr cs:CPF_02
	invoke	strcat, dx::ax, addr cs:CPTEMP
	mov	cx,_DLL_ADD
	call	init_args_find
	invoke	strcat, dx::ax, addr cs:CPF_03
	invoke	strcat, dx::ax, addr cs:CPTEMP
	mov	cx,_DLL_MOVE
	call	init_args_find
	invoke	strcat, dx::ax, addr cs:CPF_03
	invoke	strcat, dx::ax, addr cs:CPTEMP
	mov	cx,_DLL_DELETE
	call	init_args_find
	invoke	strcat, dx::ax, addr cs:CPF_03
	invoke	strcat, dx::ax, addr cs:CPTEMP
	mov	cx,_DLL_RENAME
	call	init_args_find
	invoke	strcat, dx::ax, addr CString(" %s %s")
	mov	cx,_DLL_EDIT
	call	init_args_find
	invoke	strcat, dx::ax, addr CString(" %s %s")
	mov	cx,_DLL_VIEW
	call	init_args_find
	invoke	strcat, dx::ax, addr CString(" %s %s\ %s")
	ret
    init_args_find:
	push	si
	push	di
	mov	si,cx
	shl	si,2
	mov	di,cs:[si+config_label]
	mov	si,cs:[si+config_label+2]
	mov	dx,cs
	mov	bx,offset c_entry
	mov	ah,_DZ_inientryid
	int	DZ
	or	ax,ax
	jnz	init_args_found
	mov	dx,cs
	mov	ax,di
    init_args_found:
	invoke	strcpy, cs::si, dx::ax
	pop	di
	pop	si
	ret

;-------------------------------------------------------------------------
; Function 01 - Read
;-------------------------------------------------------------------------

ARJHEADERID = 	0EA60h
ARJEXTFILE  = 	08h

S_ARJ			STRUC
arj_id			dw ?
arj_size_head		dw ?
arj_size_filehead	db ?
arj_version		db ?
arj_min_version		db ?
arj_os			db ?
arj_flag		db ?
arj_method		db ?
arj_type		db ?
arj_password		db ?
arj_time		dw ?
arj_date		dw ?
arj_compressed_size	dd ?
arj_original_size	dd ?
arj_crc			dd ?
arj_name_pos		dw ?
arj_file_access_mode	dw ?
arj_host_data		dw ?
S_ARJ			ENDS

warjreadentry PROC PASCAL, arj:word, handle:word
local	result:word
	mov	ax,arj
	invoke	osread, handle, ss::ax, SIZE S_ARJ
	cmp	ax,SIZE S_ARJ
	jne	readentry_fail
	mov	bx,arj
	cmp	[bx.arj_id],ARJHEADERID
	jne	readentry_fail
	mov	ax,[bx.arj_size_head]
	sub	ax,30
	cmp	ax,MAXENTRYNAME+4
	jbe	@F
	mov	ax,MAXENTRYNAME
    @@:	invoke	osread, handle, addr entryname, ax
	mov	dx,ax
	mov	bx,arj
	mov	ax,4
	add	ax,[bx.arj_size_head]
	sub	ax,dx
	sub	ax,30
	invoke	lseek, handle, ax, SEEK_CUR
	inc	dx
	jz	readentry_fail
	invoke	osread, handle, addr result, 2
	cmp	ax,2
	jne	readentry_fail
	mov	bx,arj		; Seek to start of next entry
	lodm	[bx.arj_compressed_size]
	mov	cx,result
	or	cx,cx
	jz	@F
	add	cx,4
	add	ax,cx
	adc	dx,0
    @@:	invoke	lseek, handle, dx::ax, SEEK_CUR
	inc	dx
	jz	readentry_fail
	invoke	unixtodos, addr entryname
	or	ax,ax
    @@:	ret
    readentry_fail:
	xor	ax,ax
	jmp	@B
warjreadentry ENDP

dll_read PROC PASCAL, wsub:dword
local   handle:word
local	entry:S_ARJ
local	extsize:word
local	fattrib:word
	push	si
	push	di
	invoke	wsfree, wsub	; free allocated file block's
	invoke	wsopenarch, wsub
	mov     handle,ax
	inc     ax
	jz      dll_read_ioerr
	lea	si,entry
	lea	di,entryname	; read main entry
	invoke	osread, handle, addr entry, SIZE S_ARJ
	cmp	ax,SIZE S_ARJ
	jne	dll_read_ioerr
	cmp	[si.arj_id],ARJHEADERID
	jne	dll_read_ioerr
	mov	ax,8
	add	ax,[si.arj_size_head]
	invoke	lseek, handle, ax, SEEK_SET
	inc	dx
	jz	dll_read_ioerr
	invoke	osread, handle, addr extsize, 2
	cmp	ax,2
	jne	dll_read_ioerr
	xor	dx,dx
	mov	ax,extsize
	or	ax,ax
	jz	dll_readmain_ok
	add	ax,4
	adc	dx,0
	invoke	lseek, handle, dx::ax, SEEK_CUR
	inc	dx
	jz	dll_read_ioerr
    dll_readmain_ok:
	invoke	warjreadentry, si, handle
	jnz     dll_read_init
    dll_read_ioerr:
	invoke	close, handle
	jmp     dll_read_fail
    dll_read_init:
	mov	bx,word ptr wsub	; add UPDIR (..) to panel
	mov	[bx.ws_count],1
	invoke	fbupdir, _W_ARCHEXT
	mov	bx,word ptr wsub
	les	bx,[bx.ws_fcb]
	mov	es:[bx],ax
	mov	es:[bx+2],dx
    dll_read_do:
	test	[si.arj_flag],ARJEXTFILE
	jnz	dll_read_while
	invoke  testentryname, wsub, addr entryname
	jz	dll_read_while
	mov	fattrib,ax
	test	al,_A_SUBDIR
	jnz	dll_read_sub
	mov	bx,word ptr wsub	; test panel's read mask (*.*)
	invoke  cmpwarg, addr entryname, [bx.ws_mask]
	jz	dll_read_while
    dll_read_sub:
	invoke	strlen, ss::di
	add	ax,size S_FBLK
	invoke	malloc, ax
	jz	dll_read_break
	mov	es,dx			; copy info to block
	mov	bx,ax
	mov	ax,fattrib
	or	ax,_A_ARCHEXT
	mov	es:[bx.fb_flag],ax
	mov	ax,[si.arj_date]
	mov	es:[bx.fb_date],ax
	mov	ax,[si.arj_time]
	mov	es:[bx.fb_time],ax
	movm	es:[bx.fb_size],[si.arj_original_size]
	push	bx
	add	bx,fb_name
	invoke	strcpy, es::bx, ss::di
	pop	ax
	mov	bx,word ptr wsub
	mov	cx,[bx.ws_count]	; add block to panel
	shl	cx,2
	les	bx,[bx.ws_fcb]
	add	bx,cx
	mov	es:[bx],ax
	mov	es:[bx+2],dx
	mov	bx,word ptr wsub
	inc	[bx.ws_count]
	mov	ax,[bx.ws_count]
	cmp	ax,[bx.ws_maxfb]
	jae	dll_read_break
    dll_read_while:			; read next file record
	invoke	warjreadentry, si, handle
	jnz	dll_read_do
    dll_read_break:
	invoke	close, handle
	mov	bx,word ptr wsub
	mov	ax,[bx.ws_count]	; return file count
    dll_read_end:
	pop	di
	pop	si
	ret
    dll_read_fail:
	mov	ax,ER_READARCH
	jmp	dll_read_end
dll_read ENDP

;-------------------------------------------------------------------------
; Function 02 - Copy
;-------------------------------------------------------------------------

arj_mklist:	; create list
	mov	al,0	; no unix path
	mov	dl,1	; use mask in directory\*.*
	invoke	dzmklist, CStr(<'ARJ.DLL: Create list file'>)
	ret

dll_copy PROC PASCAL, wsub:dword, fblk:dword, outp:dword
local	command[256]:byte
local	path[WMAXPATH]:byte
	push	di
	mov	di,offset CMD_02
	invoke	strcpy, addr path, outp
	mov	bx,ax
	invoke	strlen, dx::ax
	dec	ax
	add	bx,ax
	mov	ax,'\'
	cmp	es:[bx],al
	jne	@F
	mov	es:[bx],ah
    @@:	call	arj_mklist
	jnz	dll_copy_end
	or	bx,bx
	jnz	@F
	mov	di,offset CMD_00
    @@:	invoke	wsclrsel, wsub
	lea	ax,path
	push	ss
	push	ax
	mov	bx,word ptr wsub
	pushm	[bx.ws_file]
	lea	ax,command
	invoke	ssprintf, ax, di
	add	sp,8
	invoke	dzexec, addr command, SPAWN_EXIT
	xor	ax,ax
    dll_copy_end:
	pop	di
	ret
dll_copy ENDP

;-------------------------------------------------------------------------
; Function 03 - Add
;
; add files to <archive>\ root directory only
;-------------------------------------------------------------------------

IDD_ADDMSG LABEL WORD
incbin <inc/addmsg.idd>

dll_add PROC PASCAL, dest:dword, wsub:dword, fblk:dword
local	command[256]:byte
local	path[WMAXPATH]:byte
	mov	bx,word ptr dest
	mov	bx,word ptr [bx.ws_arch]
	mov	ax,[bx]
	or	al,al
	jz	@F
	invoke	rsmodal, addr cs:IDD_ADDMSG
	jz	dll_add_fail
    @@:	call	arj_mklist
	jnz	@F
	invoke	wsclrsel, wsub
	mov	bx,word ptr dest
	invoke	strfcat, addr path, [bx.ws_path], [bx.ws_file]
	push	dx
	push	ax
	lea	ax,command
	invoke	ssprintf, ax, offset CMD_03
	add	sp,4
	invoke	dzexec, addr command, SPAWN_EXIT
	xor	ax,ax
    @@:	ret
    dll_add_fail:
	mov	ax,ER_USERABORT
	jmp	@B
dll_add ENDP

;-------------------------------------------------------------------------
; Function 04 - Move
;
; move files to <archive>\ root directory only
;-------------------------------------------------------------------------

dll_move PROC PASCAL, dest:dword, wsub:dword, fblk:dword
local	command[256]:byte
local	path[WMAXPATH]:byte
	mov	bx,word ptr dest
	mov	bx,word ptr [bx.ws_arch]
	mov	ax,[bx]
	or	al,al
	jz	@F
	invoke	rsmodal, addr cs:IDD_ADDMSG
	jz	dll_move_fail
    @@:	call	arj_mklist
	jnz	@F
	invoke	wsclrsel, wsub
	mov	bx,word ptr dest
	invoke	strfcat, addr path, [bx.ws_path], [bx.ws_file]
	push	dx
	push	ax
	lea	ax,command
	invoke	ssprintf, ax, offset CMD_04
	add	sp,4
	invoke	dzexec, addr command, SPAWN_EXIT
	xor	ax,ax
    @@:	ret
    dll_move_fail:
	mov	ax,ER_USERABORT
	jmp	@B
dll_move ENDP

;-------------------------------------------------------------------------
; Function 06 - Delete
;-------------------------------------------------------------------------

IDD_DODELETE LABEL WORD
incbin <inc/dodelete.idd>

dll_delete PROC PASCAL, wsub:dword, fblk:dword
local	command[256]:byte
	invoke	rsmodal, addr cs:IDD_DODELETE
	dec	ax
	jnz	@F
	call	arj_mklist
	jnz	@F
	invoke	wsclrsel, wsub
	mov	bx,word ptr wsub
	pushm	[bx.ws_file]
	lea	ax,command
	invoke	ssprintf, ax, offset CMD_06
	add	sp,4
	invoke	dzexec, addr command, SPAWN_EXIT
	xor	ax,ax
    @@:	ret
dll_delete ENDP

;-------------------------------------------------------------------------
; Function 07 - Rename
;-------------------------------------------------------------------------

dll_rename PROC PASCAL, wsub:dword, fblk:dword
local	command[256]:byte
local	fname[WMAXPATH]:byte
	call	arj_mklist
	jnz	@F
	invoke	wsclrsel, wsub
	mov	bx,word ptr wsub
	add	word ptr fblk,fb_name
	invoke	strfcat, addr fname, [bx.ws_arch], fblk
	push	dx
	push	ax
	pushm	[bx.ws_file]
	lea	ax,command
	invoke	ssprintf, ax, offset CMD_07
	add	sp,4
	invoke	dzexec, addr command, SPAWN_EXIT
	xor	ax,ax
    @@:	ret
dll_rename ENDP

;-------------------------------------------------------------------------
; Function 08 - Edit
;-------------------------------------------------------------------------

dll_edit PROC PASCAL, wsub:dword, fblk:dword
local	temp[WMAXPATH]:byte
local	command[WMAXPATH]:byte
	push	si
	push	di
	mov	si,word ptr wsub
	lea	di,command
	add     word ptr fblk,fb_name
	pushm	fblk
	pushm	envtemp
	pushm	[si.ws_file]
	invoke	ssprintf, di, offset CMD_09
	add	sp,12
	invoke	dzexec, addr command, SPAWN_HIDE
	pushm	fblk
	pushm	envtemp
	invoke	ssprintf, di, CStr(<"%s\%s">)
	add	sp,8
	invoke	filexist, ss::di
	dec	ax
	jnz	dll_edit_end
	invoke	dzedit, ss::di, 0
	or	dx,dx
	jz	@F
	lea	ax,temp
	push	ss
	push	ax
	mov	bx,word ptr wsub
	pushm	[bx.ws_file]
	invoke	ssprintf, di, offset CMD_08
	add	sp,8
	invoke	dzexec, addr command, SPAWN_EXIT
	jmp	dll_edit_end
    @@:	invoke	remove, ss::di
    dll_edit_end:
	pop	di
	pop	si
	ret
dll_edit ENDP

;-------------------------------------------------------------------------
; Function 09 - View
;-------------------------------------------------------------------------

dll_view PROC PASCAL, wsub:dword, fblk:dword
local	command[128]:byte
	push	si
	push	di
	mov	si,word ptr wsub
	lea	di,command
	add     word ptr fblk,fb_name
	pushm	fblk
	pushm	envtemp
	pushm	[si.ws_file]
	invoke	ssprintf, di, offset CMD_09
	add	sp,12
	invoke	dzexec, addr command, SPAWN_NUL
	pushm	fblk
	pushm	envtemp
	invoke	ssprintf, di, CStr(<"%s\%s">)
	add	sp,8
	invoke	filexist, ss::di
	dec	ax
	jnz	@F
	invoke	dzview, ss::di, ax::ax
	invoke	remove, ss::di
    @@:	pop	di
	pop	si
	ret
dll_view ENDP

;-------------------------------------------------------------------------
; Function 11 - Exit
;-------------------------------------------------------------------------

dll_exit:
	xor	ax,ax
	iret

	END	start


