;NOTE: The libstartup code generated by LibTool opens the exec, DOS, Intuition,
;      and Graphics libraries for our library functions and stores the bases
;      at the following variables respectively. Therefore, our library code
;      doesn't have to open these libs in order use their routines, nor close
;      these libs. The next XREF statement should always be included in any
;      lib code.
;NOTE: If you need to open any other libraries, it would be good to do so from
;      within an Init vector. Remember to also add an Expunge vector which
;      closes those libs.

	XREF	_SysBase,_DOSBase,_IntuitionBase,_GfxBase

;If you need to examine your lib base structure (for some reason) make it
;visible here

	XREF	_LibBase

	XREF	_LVOForbid,_LVOPermit,_LVOAllocMem,_LVOFreeMem
	XREF	_LVOAddTail,_LVORemTail,_LVOWaitPort,_LVOGetMsg,_LVORemove
	XREF	_LVOOpenWindow,_LVOCloseWindow
	XREF	_LVOMove,_LVOText

;=============================================================
; This is the first function in the library. First it finds the mem that was
; allocated for this task when the task opened the library (i.e. from within
; GetMem). Then it copies a newWindow template to this mem. Note that it is
; ok to have newWindow global because we don't modify it at all. We simply
; copy it to a the mem that we use for the task. Actually, it would have been
; easier/quicker to get the mem from the stack, but I wanted to demo using
; the Open/Close vectors. Finally, it opens the window and returns the result.

	XDEF	MakeWindow	;make it visible to our libstartup code
MakeWindow:
	move.l	a6,-(sp)	;no lib routine should destroy d2-d7/a2-a6
;---Find this task's work buffer
	bsr.s	FindMem
	beq.s	1$
;---Copy the newWindow template to our work buffer
	movea.l	d0,a0
	moveq	#48-1,d1
	lea	newWindow(pc),a1
2$	move.b	(a1)+,(a0)+
	dbra	d1,2$(pc)
;---Open the window
	movea.l	d0,a0
	movea.l	_IntuitionBase,a6
	jsr	_LVOOpenWindow(a6)
1$	movea.l	(sp)+,a6
	rts

;=============================================================
; This finds the address of the task's work buffer allocated when the task
; opened the library. Note that this is for internal use only, and is not
; XDEF or included as a callable function in our fd file.

FindMem:
;---Stop another task from getting in here while we examine memList
;   This is what you have to do when you use globals that can be modified
;   (memList).
	movea.l	_SysBase,a6
	jsr	_LVOForbid(a6)
;---Get this task's address
	move.l	276(a6),d1
;---Find this task's allocated memory
	move.l	memList(pc),d0
2$	movea.l	d0,a0
	move.l	(a0),d0
	beq.s	1$		;return(0) if we can't find the mem!!!
	cmp.l	8(a0),d1
	bne.s	2$
;---Skip the first 12 bytes
	moveq	#12,d0
	add.l	a0,d0
1$	move.l	d0,-(sp)
;---Permit again
	jsr	_LVOPermit(a6)
;---Return 0 or the address of our "work buffer"
	move.l	(sp)+,d0
	rts

;=============================================================
; This is the second function in the library. It moves to the passed x and
; y coordinates, prints the passed msg in the passed window, then waits for
; a CLOSEWINDOW press before returning.

	XDEF	PrintMsg
PrintMsg:
	movem.l	a2/a3/a6,-(sp)
	movea.l	a0,a2
	movea.l	a1,a3
;---Move to (x,y)
	movea.l	50(a2),a1	;RastPort
	movea.l	_GfxBase,a6
	jsr	_LVOMove(a6)
;---(Get its length) and print the msg	
	movea.l	a3,a0
1$	move.b	(a3)+,d0
	bne.s	1$
	subq.l	#1,a3
	suba.l	a0,a3
	move.l	a3,d0		;the # of bytes not counting end NULL
	beq.s	2$
	movea.l	50(a2),a1
	jsr	_LVOText(a6)
;---Wait for CLOSEWINDOW (the only msg we expect), remove it, and return
2$	movea.l	_SysBase,a6
	movea.l	86(a2),a0
	jsr	_LVOWaitPort(a6)
	movea.l	86(a2),a0
	jsr	_LVOGetMsg(a6)
	movem.l	(sp)+,a2/a3/a6
	rts

;=============================================================
; This is the third function in the library. It closes the passed window.

	XDEF	RemWindow
RemWindow:
	move.l	a6,-(sp)
	movea.l	_IntuitionBase,a6
	jsr	_LVOCloseWindow(a6)
	movea.l	(sp)+,a6
	rts

;=======================================================================
; These next 2 are called when an application opens and closes the lib
; respectively. The Open vector allocates a work buffer of 48 bytes for
; a newWindow structure, plus 8 bytes to link it into memList, plus 4 bytes
; to store the app's task address (which is what we use to indentify its
; work buffer in the list). The Close vector simply removes/frees the closing
; task's work buffer.
; Note that we don't have to Forbid/Permit when we access the memList because
; the task switching is already forbidden when these routines are called.
; For this reason, we should never do any kind of Wait() in here.
; We also don't have to save a6 since that is already done for us as well

	XDEF	OpenUp
OpenUp:
;---Get a zeroed, work buffer
	movea.l	_SysBase,a6
	moveq	#8+4+48,d0
	moveq	#1,d1
	bset.l	#16,d1
	jsr	_LVOAllocMem(a6)
	move.l	d0,d1
	beq.s	1$		;return 0
;---Store the task address
	movea.l	d0,a1
	move.l	276(a6),8(a1)
;---Link it into memList
	lea	memList(pc),a0
	jsr	_LVOAddTail(a6)
	moveq	#1,d0		;OK
1$	rts

	XDEF	CloseUp
CloseUp
	move.l	a2,-(sp)
;---Find the work buffer
	bsr	FindMem
	beq.s	1$
;---Remove it from the list
	movea.l	d0,a2
	suba.w	#12,a2
	movea.l	a2,a1
	jsr	_LVORemove(a6)
;---Free it
	movea.l	a2,a1
	moveq	#8+4+48,d0
	jsr	_LVOFreeMem(a6)
1$	movea.l	(sp)+,a2
	rts

;an initialized, empty list to hold the address of each task's work buffer
memList	dc.l	memList+4
	dc.l	0
	dc.l	memList

;a newWindow structure to be used as a template
newWindow:
	dc.w	10,10,200,180
	dc.b	0,1
;CLOSEWINDOW
	dc.l	$200
;SMART_REFRESH|ACTIVATE|WINDOWDRAG|WINDOWDEPTH|WINDOWSIZING
	dc.l	$100f
	dc.l	0,0
	dc.l	0
	dc.l	0,0
	dc.w	100,35,-1,-1
	dc.w	1
