**************************************************************************
*
* The GNO Shell Project
*
* Developed by:
*   Jawaid Bazyar
*   Tim Meekins
*
**************************************************************************
*
* SV.ASM
*   By Tim Meekins
*
* String Vector routines.
*
**************************************************************************

               keep  o/sv
               mcopy m/sv.mac
                         
**************************************************************************
*
* Allocate a string vector array
*
**************************************************************************

sv_alloc	START

ptr	equ	0
space	equ	ptr+4

	subroutine (2:size),space

	lda	size
	inc	a	;for size and count
	inc	a	;at least one null entry
	asl	a
	asl	a
	pea	0
	pha
	jsl	~NEW
	sta	ptr
	stx	ptr+2

	ldy	#2
	lda	size
	sta	[ptr],y
	lda	#0
	sta	[ptr]
	ldy	#4

	ldx	size

init	sta	[ptr],y
	iny
	iny
	sta	[ptr],y
	iny
	iny
	dex
	bpl	init	;not bne so that extra null at end

	add4	ptr,#4,ptr

	return 4:ptr

	END

**************************************************************************
*
* Add a string to the string vector
*
**************************************************************************

sv_add	START

p	equ	0
base	equ	p+4
space	equ	base+4

	subroutine (4:vect,4:string,2:allocflag),space

	sub4	vect,#4,base

	ldy	#2
	lda	[base],y
	cmp	[base]
	beq	exit	;ack, the vector is full!
;
; 1 = allocate memory, 0 = use string as is...
;
	lda	allocflag
	beq	asis
	
	pei	(string+2)
	pei	(string)
	jsr	cstrlen
	inc	a
	pea	0
	pha
	jsl	~NEW
	sta	p
	stx	p+2

	pei	(string+2)
	pei	(string)
	phx
	pha
	jsr	copycstr
               bra	doit

asis	mv4	string,p

doit	lda	[base]
	tax
	asl	a
	asl	a
	tay
	lda	p
	sta	[vect],y
	iny
	iny
	lda	p+2
	sta	[vect],y

	txa	
	inc	a
	sta	[base]

exit	return

	END

**************************************************************************
*
* Dispose a string vector
*
**************************************************************************

sv_dispose	START

p	equ	0
space	equ	p+4

	subroutine (4:vect),space

	sub4	vect,#4,p

loop	lda	[p]
	beq	done
	asl	a
	asl	a
	tay
	lda	[vect],y
	tax
	iny
	iny
	lda	[vect],y
	pha
	phx
	jsl	nullfree
	lda	[p]
	dec	a
	sta	[p]
	bra	loop

done	pei	(p+2)
	pei	(p)
	jsl	nullfree

	return

	END

**************************************************************************
*
* Column print a string vector
*
**************************************************************************

sv_colprint	START

numrow	equ	0
numcol	equ	numrow+2
base	equ	numcol+2
maxlen	equ	base+4
space	equ	maxlen+2

	subroutine (4:sv),space
	
	sub4	sv,#4,base
;
; Find the maximum string length
;
	lda	#1
	sta	maxlen

	ldy	#0
	lda	#0
lenloop	pha
	lda	[sv],y
	tax
	iny
	iny
	lda	[sv],y
	iny
	iny
	phy
	pha
	phx
	jsr	cstrlen
	cmp	maxlen
	bcc	nextlen
	sta	maxlen
nextlen	ply
	pla
	inc	a
	cmp	[base]
	bcc	lenloop
;
; add one for a space
;
	inc	maxlen
;
; calculate the number of columns....this is probably simpler than doing
; a divide..
;
	ldx	#0
	txa
	dex
	clc
colloop	inx
	adc	maxlen
	cmp	#80
	bcc	colloop
	cpx	#6+1
	bcc	okcol
	ldx	#6	;limit of 6 columns
okcol	stx	numcol
;
; recalculate the width
;
	UDivide (#80,@x),(maxlen,@a)
;
; calculate the height
;
	lda	[base]
	UDivide (@a,numcol),(numrow,@x)
	cpx	#0
	beq	foocol
	inc	numrow
foocol	anop
;
; find the index for each column...
;                                  
	lda	#0
	tax
	clc
mkidxloop	sta	offtbl,x
	inx
	adc	numrow
	cmp	[base]
	bcc	mkidxloop
;
; well....I think we can print now (yay!)
;
	ldx	#0
printloop	lda	offtbl,x
	and	#$FF
	cmp	[base]
	bcs	nextprint0
	inc	a
	short	a
	sta	offtbl,x
	long	a
	phx
	dec	a
	asl	a
	asl	a
	tay
	lda	[sv],y
	tax
	iny
	iny
	lda	[sv],y
	pha
	phx
	tax
	lda	1,s
	jsr	puts
	jsr	cstrlen
tabit	cmp	maxlen
	bcs	nextprint
	pha
	lda	#' '
	jsr	putchar
	pla
	inc	a
	bra	tabit
nextprint	plx
	inx
	cpx	numcol
	bcc	printloop
nextprint0	jsr	newline
	ldx	#0
	dec	numrow
	bne	printloop

doneprint	return

offtbl	ds	7

	END

**************************************************************************
*
* Sort a string vector
*
**************************************************************************

sv_sort	START

space	equ	0

	subroutine (4:sv),space

	pei	(sv+2)
	pei	(sv)
	sub4	sv,#4,sv
	pea	0
	lda	[sv]
	dec	a
	pha
	jsl	_qsort

	return

	END

_qsort	PRIVATE

vleft	equ	0
i	equ	vleft+4
last	equ	i+2
ptr2	equ	last+2
ptr1	equ	ptr2+4
idx1	equ	ptr1+4
space	equ	idx1+2

	subroutine (4:sv,2:left,2:right),space
;
; if (left >= right)
;    return;
;
	lda	right	;if one or two elements do nothing
	jmi	exit
	cmp	left
	jcc	exit
;
; swap(v, left, (left + right)/2);
;
	lda	left
	asl	a
	asl	a
	sta	idx1
	tay
	lda	[sv],y
	sta	ptr1
	iny
	iny
	lda	[sv],y
	sta	ptr1+2
	add2	left,right,@a
	lsr	a
	asl	a
	asl	a
	tay
	lda	[sv],y
	sta	ptr2
	lda	ptr1
	sta	[sv],y
	iny
	iny
	lda	[sv],y
	sta	ptr2+2
	lda	ptr1+2
	sta	[sv],y
	ldy	idx1
	lda	ptr2
	sta	[sv],y
	iny
	iny
	lda	ptr2+2
	sta	[sv],y
;
; last = left;
;
	lda	left
	sta	last

	asl	a
	asl	a
	tay	
	lda	[sv],y
	sta	vleft
	iny
	iny
	lda	[sv],y
	sta	vleft+2
;
; for (i=left+1; i <=right; i++)
;
	lda	left
	inc	a
	sta	i
forloop	lda	i
	cmp	right
	beq	okloop
	bcs	endloop
okloop	anop
;
;     if (strcmp(v[i],v[left]) < 0)
;
	asl	a
	asl	a
	tay
	lda	[sv],y
	tax
	iny
	iny
	lda	[sv],y
	pha
	phx
	pei	(vleft+2)
	pei	(vleft)
	jsr	cmpcstr
	bpl	nextloop
;
;        swap (v, ++last, i)
;	
	inc	last
	lda	last
	asl	a
	asl	a
	sta	idx1
	tay
	lda	[sv],y
	sta	ptr1
	iny
	iny
	lda	[sv],y
	sta	ptr1+2
	lda	i
	asl	a
	asl	a
	tay
	lda	[sv],y
	sta	ptr2
	lda	ptr1
	sta	[sv],y
	iny
	iny
	lda	[sv],y
	sta	ptr2+2
	lda	ptr1+2
	sta	[sv],y
	ldy	idx1
	lda	ptr2
	sta	[sv],y
	iny
	iny
	lda	ptr2+2
	sta	[sv],y

nextloop	inc	i
	jmp	forloop
;
; swap(v, left, last)
;                            
endloop	lda	left
	asl	a
	asl	a
	sta	idx1
	tay
	lda	[sv],y
	sta	ptr1
	iny
	iny
	lda	[sv],y
	sta	ptr1+2
	lda	last
	asl	a
	asl	a
	tay
	lda	[sv],y
	sta	ptr2
	lda	ptr1
	sta	[sv],y
	iny
	iny
	lda	[sv],y
	sta	ptr2+2
	lda	ptr1+2
	sta	[sv],y
	ldy	idx1
	lda	ptr2
	sta	[sv],y
	iny
	iny
	lda	ptr2+2
	sta	[sv],y
;
; qsort(v, left, last-1)
;
	pei	(sv+2)
	pei	(sv)
	pei	(left)
	lda	last
	dec	a
	pha
	jsl	_qsort
;
; qsort(v, last+1, right)
;
	pei	(sv+2)
	pei	(sv)
	lda	last
	inc	a
	pha
	pei	(right)
	jsl	_qsort
                     
exit	return

	END