*******************************************************************************
*
* RoundRect Window
*
* (C)  Copyright Apple Computer, Inc. 1988-1990
* All rights reserved.
*
* Developer Technical Support Apple II Sample Code
*
* by Keith Rollin
*
* This file contains the definition procedure (defProc) for a custom window.
* This window acts like a fairly normal, but limited, window, and has the
* following features:
*
*     - The corners are curved. The radius of the corners can be specified.
*     - It always has a title bar, which always has a solid background color
*       and title in it. The titlebar redraws itself in response to being
*       activated and deactivated.
*     - A GoAway box can optionally be included in the title bar. The zoom
*       box is not drawn or supported.
*     - There are no infobars or frame controls (like scrollbars).
*     - A color table can be provided, or a default color table can be used.
*     - The window can be dragged and grown.
*     - TaskMaster is supported.
*
*******************************************************************************

	EJECT
*******************************************************************************
*
RRectDefProcData	RECORD
*
* Description:	Equates and variables used by the RoundRect Window defProc.
*
*
*******************************************************************************

; stack/direct page frame. These equates are used to access information that
; is passed to the window DefProc on the stack.


	DefineStack

OrigD	word	; saved Direct Page register
OrigB	byte	; saved Data Bank register
work	long	; a LONG of workspace
workRgn	long	; a LONG of workspace
returnAddr	block 3	; RTL address
param	long	; operation specific parameter
theWindow	long	; This is NOT a pointer to the window.
		; This is a pointer to a window record.
		; This means that it points to
		; owNext, not the grafPort part of
		; a window record!!
operation	word	; operation to perform
windGlobals	long	; pointer to handy values
result	long	; place to store operation result

;
; Window Globals table
;
lineW	equ 0	; width of vertical lines
titleHeight	equ lineW+2	; Height of standard title bar
titleYPos	equ titleHeight+2	; Y offset for title in std. titlebar
closeHeight	equ titleYPos+2	; height of close icon.
closeWidth	equ closeHeight+2	; width of close icon.
defWindClr	equ closeWidth+2	; pointer to default color table
windIconFont	equ defWindClr+4	; handle to current window icon font
screenMode	equ windIconFont+4	; TRUE if 640 mode, FALSE if 320
pattern	equ screenMode+2	; Temporary pattern buffer
callerDPage	equ pattern+32	; DP of last caller to TaskMaster
callerDataB	equ callerDPage+2	; DBR of last caller to TaskMaster

;
; NewWindow Parameter list
;
	DSect 0
wParamID	word	; should be zero for custom windows
wMe	long	; address of customProc
wFrameBits	word	; flags that determine window type
wPosition	block 8	; used as portRect for contents
wPlane	long	; window Plane
wStorage	long	; storage for the window record
; These 2 are copied in one pass. Keep together and in this order.
wRefCon	long	; refCon
wContDraw	long	; routine that draw the contents
; Everything past here is copied after the wFrame field of the Window Record.
wCustom	block 0	; start of custom information section
wTitle	long	; pointer to window's title
wColorTable	long	; pointer to color table
wRV	word	; vertical radius of corners
wRH	word	; horizontal radius of corners
wEnd	block 0

;
; My extensions for this custom window
;
	DSect windSize
xowTitle	long	; pointer to window's title
xowColorPtr	long	; pointer to our color table (if any)
xowRV	word	; vertical radius of corners
xowRH	word	; horizontal radius of corners
xowEnd	block 0

;
; Position of the GoAway box
;
GAX	equ 10
GAY	equ 2

;
; Scratch areas
;
contRect	ds.b 8
strucRect	ds.b 8
pRect	ds.b 8

	ENDR


	EJECT
*******************************************************************************
*
RRectDefProc	PROC
*
* Description:	Main Procedure for the RoundRect custom window definition.
*	This routine creates a suitable environment for us (saves
*	the old Direct Page and Data Bank registers and makes us
*	some new ones), calls the appropriate routine based on
*	the value of 'operation', and returns to the Window
*	Manager with the Carry bit and Y register set correctly.
*
*
* Inputs:
*	On entry, the stack contains the following values:
*
*	-------- previous contents --------
*	LONG  result	space for result
*	LONG  windGlobals	pointer to WMgr globals
*	WORD  operation	operation number to be performed
*	LONG  theWindow	ptr to window's record
*	LONG  param	additional parameter for some ops.
*	3 Bytes	RTL Address
*	      <------------ Stack Pointer
*
* Outputs:	Carry = clear if no error
*	Carry = set if error, and Y has error number.
*
* External Refs:
	import rrDraw
	import rrHit
	import rrCalcRgns
	import rrNew
	import rrDispose
	import rrGetDrag
	import rrGrowFrame
	import rrRecSize
	import rrPosition
	import rrBehind
	import rrCallDefProc
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData
wMaxTask	equ 10

; The first thing we do is get a little Direct Page space by using the stack.
; First, push on some scratch space onto the stack, then save the old values
; of the Data Bank Register and the Direct Page Register. Set the Data Bank
; Register to the same value as the Program Bank Register, and then transfer
; the Stack Pointer to the Direct Page Register. This gives us a stack and
; Direct Page that looks like this:
;
; Direct Page location  SIZE  What it is
;	25  LONG  result
;	21  LONG  windGlobals
;	19  WORD  operation
;	15  LONG  theWindow
;	11  LONG  param
;	 8  3 Bytes RTL Address
;	 4  LONG  workspace
;	 3  BYTE  old Data Bank Register
;	 1  WORD  old Direct Page Register
;	        <--- stack pointer

	pha	; Push on 8 bytes of workspace.
	pha
	pha
	pha

	phb	; Save the data bank register
	phd	; Save the direct page register

; Set the Data Bank register to the Program Bank register. This allows short
; (2 byte) addressing, as opposed to the 3 byte addressing we would have had
; to use if the Data Bank register were set to some unknown value.

	phk	; Set up my own DBR
	plb

; Set the direct page to the stack. This lets us use some of the values passed
; to us as 'zero-page' pointers (like theWindow).

	tsc	; Set up my own Direct Page
	tcd

; Zero out 'result' as default.

@a	stz <result	; zero this out to start with
	stz <result+2

; Find out which operation to perform, check its range, and, if it is OK,
; convert it to an index into a jump table. Execute the routine.

	lda <operation
	cmp #wMaxTask+1
	bcs OutOfRange

	asl a
	tax
	jsr (opTable,x)

; The operation has been carried out. Strip the parameters off of the stack
; and move the return address up, making sure to leave the 'result'. Gotta be
; careful to preserve the carry flag here!!!

OutOfRange	lda <returnAddr	; move the return address up
	sta <result-3
	lda <returnAddr+1
	sta <result-2

	tsc	; get the stack ptr so we can change it

	pld	; restore the DP and DBR
	plb

	php	; save the state of the carry
	clc	; fudge the stack pointer
	adc #result-4
	plp	; restore the carry state
	tcs	; point the stack pointer to the return
		; address we moved up

	rtl	; back to the window manager

opTable	dc.w rrDraw	; Draw the specified part
	dc.w rrHit	; determine where we hit
	dc.w rrCalcRgns	; Calculate Struc and Content Regions
	dc.w rrNew	; Perform initialization
	dc.w rrDispose	; Close window
	dc.w rrGetDrag	; Dragging to be done
	dc.w rrGrowFrame	; Grow the frame
	dc.w rrRecSize	; Return our window record size
	dc.w rrPosition	; Return window pos/size
	dc.w rrBehind	; Return plane placement
	dc.w rrCallDefProc	; Perform special stuff

	ENDP

	EJECT
*******************************************************************************
*
rrDraw	PROC
*
* Description:	Draw the specified part of the window.
*
* We draw the window frame (part $0000) in the following way:
*
*   1. Save various QuickDraw states that we will be changing.
*   2. Set the pen to normal.
*   3. Get the rectangle of our structure region.
*   4. Get a pointer to the color table we'll be using.
*   5. Set the color of the title bar (background). This changes
*      depending on whether the window is active or not.
*   6. Draw the title bar with PaintRect.
*   7. Set the color to the outline color.
*   8. Draw the main part of the frame with FrameRRect.
*   9. Draw the line that divides the title bar from the content region.
*  10. Calculate and position the pen for the string title.
*  11. Set the color for the title. Again, this changes depending on
*      whether the window is active or not.
*  12. If the window is active, call the standalone routine that draws
*      the close box (part $0001).
*  13. Restore the QuickDraw state we saved and return.
*
*
* Inputs:	param  = specification of part to draw:
*
*	     0 = draw the entire window
*	     1 = draw the go-away region
*	     2 = draw the zoom region
*	     3 = draw the info bar
*
*	If the high bit of param is set, then draw the item in
*	its highlighted state. Note: to determine whether to draw
*	a window titlebar in its active or inactive state, look
*	at the fHilite flag in the window record.
*
* Outputs:	result = zero
*	carry  = clear
*
* External Refs:	NONE
*
* Entry Points:
	entry drawFrame	; called by rrSetxxxx routines when a
		; field is changed.
*
*******************************************************************************
	with RRectDefProcData

	lda <param	; find out which part to draw
	asl a	; turn into an index into a jump table
	tax
	jsr (partToDraw,x)

	clc
	rts

partToDraw	dc.w drawFrame
	dc.w drawGoAway
	dc.w drawZoomBox
	dc.w drawInfoBar

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Draws the entire frame of a window. This includes the go-away box and any
; other parts of the frame that you may implement (like a zoom box, an
; infobar, scrollbars, grow box, etc.
;
drawFrame	pha	; save the text mode (on the stack!)
	_GetTextMode

	pha
	_GetPenMode

	pha	; and the color (on the stack!)
	_GetForeColor

	_PenNormal

	jsr GetStrucRect

	jsr SetColorTable	; put ptr to a color table into 'work'

;
; Now draw the background of the window. Set the color to the backbround color
; in the color table, then do a PaintRect to draw it all.
;
	jsr SetBGColor

	ldy #6	;Make a local rectangle that
@a	lda strucRect,y	;encompasses the title bar.
	sta pRect,y
	dey
	dey
	bpl @a
	ldy #titleHeight
	clc
	adc [<windGlobals],y
	dec a
	sta pRect+4
	inc pRect

	pha	;Make a rectangular region the
	pha	;same size as this rectangle.
	_NewRgn
	lda 1,s
	sta <workRgn
	lda 3,s
	sta <workRgn+2
	pea pRect>>16
	pea pRect
	_RectRgn

	stz offset
	stz offset+2
	PushLong #offset
	_LocalToGlobal
	pei <workRgn+2
	pei <workRgn
	lda offset+2
	pha
	lda offset
	pha
	_OffsetRgn

	ldy #owStrucRgn+2	; get the handle from the window record
	lda [<theWindow],y
	pha
	dey
	dey
	lda [<theWindow],y
	pha
	pei <workRgn+2
	pei <workRgn
	pei <workRgn+2
	pei <workRgn
	_SectRgn

	stz offset
	stz offset+2
	PushLong #offset
	_GlobalToLocal
	pei <workRgn+2
	pei <workRgn
	lda offset+2
	pha
	lda offset
	pha
	_OffsetRgn

	pei <workRgn+2
	pei <workRgn
	pea 2
	pea 0
	_InsetRgn

	pei <workRgn+2
	pei <workRgn
	_PaintRgn

;
; Draw the frame. Set the outline color and the Pen Width, and use
; 'strucRect' to call FrameRRect.
;

	ldy #oframeColor	; set the outline color
	lda [<work],y	; in bits 7-4
	lsr a
	lsr a
	lsr a
	lsr a
	and #%00001111
	pha
	_SetSolidPenPat

	ldy #lineW	; now set up the pen size by using the
	lda [<windGlobals],y ; pen width value the Window Manager
	pha	; passes to us in the Globals section.
	PushWord #1	; hardcode the height to 1
	_SetPenSize

	PushLong #strucRect	; now draw the entire frame
	ldy #xowRH	; these are the radii of the corners
	lda [<theWindow],y
	pha
	ldy #xowRV
	lda [<theWindow],y
	pha
	_FrameRRect

	lda strucRect	; calculate the VPos of the dividing
	ldy #titleHeight	; line.
	clc
	adc [<windGlobals],y
	dec a

	ldx strucRect+6	; push on first X/Y coordinate of a
	dex	; moveTo/lineTo sequence
	dex
	phx
	pha

	ldx strucRect+2	; the other X/Y coordinate
	phx
	pha

	_MoveTo	; draw the dividing line
	_LineTo

; Position and draw the title. Use 'oTitleColor' in the color table.

	jsr GetStringXPos

	PushWord XPos	; Next position to draw the title
	ldy #titleYPos	; let the window manager tell us its
	PushWord [<windGlobals],y ; vertical position.
	_Moveto

	PushWord #modeForeCopy ; set mode to our liking
	_SetTextMode

	jsr SetTitleColor	; set up colors accordingly

	PushLong TitlePtr	; draw the title
	_DrawString

	jsr WindowActive	; Is the window active? If so
	beq noGoAway	; don't grow goAway box

	ldy #owFrame	; does this window have a close
	lda [<theWindow],y	; box?
	and #fClose
	beq noGoAway	; no so don't draw one.

	jsr drawGoAway

noGoAway
	_SetForeColor	; restore the color and the mode
	_SetPenMode
	_SetTextMode

	rts

offset	ds.w 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Draw JUST the go-away box in the frame. This will ususally be called when
; TrakGoAway needs to (un)hilite it, but it could really be called at any
; time.

drawGoAway
	jsr SetColorTable	; get a pointer to color table

	pha	; save the text mode (on the stack!)
	_GetTextMode

	pha	; and the color (on the stack!)
	_GetForeColor

	pha	; and the color (on the stack!)
	_GetBackColor

	PushWord #modeCopy	; set mode to our liking
	_SetTextMode

	ldy #otitleColor	; set the text color
	lda [<work],y
	and #%00001111
	pha
	_SetForeColor

	ldy #otBarColor	; set the background
	lda [<work],y
	and #%00001111
	pha
	_SetBackColor

	pha	; save the current font so that we
	pha	; can switch to the Window Manager
	_GetFont	; icon font.
	PullLong OldFont

	ldy #windIconFont+2	; Get the Window icons from the
	PushWord [<windGlobals],y ; window globals area
	dey
	dey
	PushWord [<windGlobals],y
	_SetFont

	PushWord #GAX	; X position for goaway
	PushWord #GAY	; Y ditto
	_MoveTo

	lda <param+2	; how are we to draw this?
	bmi DrawHilited

	PushWord #0	; draw a normal go-away box
	bra DrawIt
DrawHilited	PushWord #1	; draw a hilited go-away box
DrawIt	_DrawChar

	PushLong OldFont	; put the old font back
	_SetFont

	_SetBackColor	; restore the mode and color
	_SetForeColor	; restore the mode and color
	_SetTextMode

	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; These aren't implemented.

drawZoomBox
drawInfoBar
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Utility routines for DrawFrame
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Check the window record to see if there is a pointer to a
; color table there. If there is one, put it into 'work' for
; later use. If there isn't one, use the default provided us
; by the Window Manager in WindGlobals.
;

SetColorTable
	ldy #xowColorPtr	; set what is pointed to in the
	lda [<theWindow],y	; window record. Store it into
	sta <work	; 'work' assuming that it is not
	iny	; zero.
	iny
	lda [<theWindow],y
	sta <work+2
	ora <work	; is it really zero?
	bne done	; no, so use it.

	ldy #defWindClr	; yes, it is zero. Use the defaults.
	lda [<windGlobals],y
	sta <work
	iny
	iny
	lda [<windGlobals],y
	sta <work+2
done
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Do some math to determine where the title string will go. We use
; the formula: (midpoint of the window) - (half the length of the string)
;
;     (left + (right - left) / 2)) - (StringWidth) / 2
;
; which reduces to:
;
;     (left + right - StringWidth) / 2
;

GetStringXPos
	ldy #xowTitle+2	; get the offset in the record to the
	lda [<theWindow],y	; title
	sta TitlePtr+2
	dey
	dey
	lda [<theWindow],y
	sta TitlePtr

	pha	; find out how long it is to center it
	PushLong TitlePtr
	_StringWidth
	PullWord XPos	; save it here for a little bit
;
; now find the left edge of the string by using the equation:
;  (windLeft+windRight-strLen)/2
;
	ldy #oport+oportRect+6 ; get the right edge of the window
	lda [<theWindow],y
	dey
	dey
	dey
	dey
	clc
	adc [<theWindow],y	; add the right edge
	sec
	sbc XPos	; subtract the string's width
	lsr a	; divide it all by two
	sta XPos	; save the left edge starting position
	rts



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Get the boundsRect of the StrucRgn in the window record. This allows us
; to do a simple FrameRRect(portRect), which is a lot faster for drawing
; the frame than FrameRgn(strucRgn).

	Entry GetStrucRect	; also called from myDragRoutine
GetStrucRect
	ldy #owStrucRgn	; get the handle from the window record
	lda [<theWindow],y
	sta <work
	iny
	iny
	lda [<theWindow],y
	sta <work+2

	ldy #2	; now dereference into a pointer
	lda [<work],y
	tax
	lda [<work]
	sta <work
	stx <work+2

	ldy #2+6	; copy the rgnBBox into pRect
	ldx #6
loop
	lda [<work],y
	sta strucRect,x
	dey
	dey
	dex
	dex
	bpl loop

	PushLong #strucRect
	_GlobalToLocal

	PushLong #strucRect+4
	_GlobalToLocal
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Find the state of the window (whether it's active or not), and set
; the BackGround color of the Title bar accordingly. These colors are
; obtained from the color table pointed to by 'work'.

SetBGColor
	jsr WindowActive	; drawing an inactive window?
	beq Inact1	; yes, set the right color

	ldy #otBarColor	; set the background color
	lda [<work],y
	and #%00001111	; in bits 3-0
	pha
	bra SetIt1

Inact1
	ldy #otitleColor	; set the background color
	lda [<work],y
	xba	; in bits 11-8
	and #%00001111
	pha

SetIt1
	_SetSolidPenPat
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; We are about to draw the title in the title bar. This routine gets
; and sets the color for that based on the entry in the color table
; pointed to by 'work'.

SetTitleColor
	jsr WindowActive	; is this an inactive window?
	beq Inact2	; yes

	ldy #otitleColor	; set the text color
	lda [<work],y
	and #%00001111	; in bits 3-0
	pha
	bra SetIt2

Inact2
	ldy #otitleColor	; set the text color
	lda [<work],y
	lsr a	; in bits 7-4
	lsr a
	lsr a
	lsr a
	and #%00001111
	pha

SetIt2
	_SetForeColor
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Short utility routine that returns z=1 if the window is active
; and z=0 if not.
;

WindowActive
	ldy #owFrame
	lda [<theWindow],y
	and #fHilited	; return z=1 if active window
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Local Data Storage
;

TitlePtr	ds.b 4
XPos	ds.b 2
OldFont	ds.b 4	; holds old font when we switch to
		; the Window Manager font
	ENDP

	EJECT
*******************************************************************************
*
rrHit	PROC
*
* Description:	Test to see which part of the window was hit (if any).
*
*
* Inputs:	param  = point to test
*	     bits 0-15 = Y-coord;
*	     bits 16-31 = X-coord.
*	    (in local coordinates)
*
* Outputs:	result =  0 wNoHit       Not on the window at all
*	         20 wInDrag      in Drag bar region
*	        *21 wInGrow      in Grow region
*	         22 wInGoAway    in Go-away region
* 	        *23 wInZoom      in Zoom region
*	        *24 wInInfo      in Info bar
*	         27 wInFrame     in the window, but none of above
*	carry  = clear
*	(Result numbers with an asterisk (*) next to them are
*	 not supported in this window)
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

	lda <param	; Make a copy of this so that it will
	sta myLocalPoint	; be easier push its address onto the
	lda <param+2	; stack.
	sta myLocalPoint+2

	PushLong #myLocalPoint
	_LocalToGlobal

; Check to see if the mouse was clicked in the strucRgn, which is also
; in global coordinates.

	pha	; room for result
	PushLong #myLocalPoint ; push a pointer to the point
	ldy #owStrucRgn+2	; push on strucRgn from theWindow
	lda [<theWindow],y
	pha
	dey
	dey
	lda [<theWindow],y
	pha
	_PtInRgn
	pla	; did we hit the strucRgn?
	beq done	; no, return no hit

	jsr ckGoAway	; did we hit the goaway box?
	bne done	; if so, it returns wInGoAway

	ldy #owFrame	; is the window draggable?
	lda [<theWindow],y
	and #fMove
	beq notDraggable	; no, return wInFrame part

	lda <param	; load in the Y coordinate
	ldy #titleHeight
	cmp [<windGlobals],y ; is it in the title region
	bge notDraggable	; no, so return wInFrame.

	lda #wInDrag	; return wInDrag
	bra done

notDraggable
	lda #wInFrame	; fall to exit routine

done
	sta <result
	clc
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
ckGoAway
;
; See if the mouse button was clicked while the cursor was in the
; goaway box. We simply use PtInRect for this.
;
; The window must both be active and have a close box in order for
; us to return a 'wInGoAway' condition.
;

	ldy #owFrame	; Check for these conditions in
	lda [<theWindow],y	; one blow. If both bits are set,
	and #fHilited+fClose ; then check to see if we landed in
	cmp #fHilited+fClose ; the close box. If both are not
	bne notInGoAway	; set, then leave.

	ldy #closeHeight	; calculate the dimensions of the
	lda [<windGlobals],y ; goAway box.
	clc
	adc goAwayRect
	sta goAwayRect+4
	ldy #closeWidth
	lda [<windGlobals],y
	clc
	adc goAwayRect+2
	sta goAwayRect+6

	lda <param	; we need this back in global
	sta myLocalPoint	; coordinates
	lda <param+2
	sta myLocalPoint+2

	pha	; room for result
	PushLong #myLocalPoint ; check the mouse click
	PushLong #goAwayRect
	_PtInRect
	pla
	beq notInGoAway	; not there, return zero
	lda #wInGoAway	; hit close box, return wInGoAway
	bra doneGoAway

notInGoAway
	lda #wNoHit
doneGoAway
	rts

myLocalPoint	ds.b 4
goAwayRect	dc.w GAY,GAX,0,0

	ENDP

	EJECT
*******************************************************************************
*
rrCalcRgns	PROC
*
* Description:	Calculate the content and structure regions of the window
*	in Global coordinates.
*
*
* Inputs:	theWindow's portRect and boundsRect will be set
*	appropriately. NOTE: The strucRgn and contRgn must be
*	returned in GLOBAL coordinates. However, while the
*	settings of the portRect and boundsRect show the relative
*	positioning of the window on the desktop, they do not give
*	a rectangle in global coordinates on which we can base our
*	calculations. The routine "GetpRect" shows the correct way
*	to get a rectangle in global coordinates on which you
*	should base your calculations.
*
* Outputs:	result =  0
*	carry  = clear
*	theWindow.StrucRgn = frame region
*		(region handle already allocated)
*	theWindow.ContRgn = content region
*		(region handle already allocated)
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

	jsr GetpRect	; get portRect; convert to Globals
;
; Create the rectangle we will use for creating the strucRgn. This is
; calculated based on the portRect, titleHeight, and screen mode.
;
	ldy #titleHeight	; Get the suggested height of titlebar
	lda contRect	; Raise the height of the strucRect by
	sec	;    that much.
	sbc [<windGlobals],y
	sta strucRect

	lda contRect+4	; lower bottom of the strucRect by 1
	ina
	sta strucRect+4

	ldy #lineW	; adjust width of the strucRect based
	lda contRect+2	; on the size of the lineWidth
	sec
	sbc [<windGlobals],y ; one linewidth on the left...
	sta strucRect+2

	lda contRect+6
	clc
	adc [<windGlobals],y ; ...and on the right.
	sta strucRect+6

; now create the Content Region by doing a FrameRRect on the contRect, and
; adding a square region to it. First create a round rect region of the full
; content size.

	_OpenRgn

	PushLong #contRect
	ldy #xowRH	; these are the radii of the corners
	PushWord [<theWindow],y
	ldy #xowRV
	PushWord [<theWindow],y
	_FrameRRect

	ldy #owContRgn+2	; push on the handle of the content
	lda [<theWindow],y	; region stored in the window record
	sta ContRgnHandle+2
	pha
	dey
	dey
	lda [<theWindow],y
	sta ContRgnHandle
	pha
	_CloseRgn

; Now create a square region to fill in the small upper corners.

	pha
	pha
	_NewRgn
	PullLong TempRgn

	lda contRect
	clc
	ldy #xowRV
	adc [<theWindow],y
	sta contRect+4

	PushLong TempRgn
	PushLong #contRect
	_RectRgn

; Add the two regions together.

	PushLong ContRgnHandle
	PushLong TempRgn
	PushLong ContRgnHandle
	_UnionRgn

	PushLong TempRgn
	_DisposeRgn

; now create the Structure Region by doing a FrameRRect on the strucRect.

	_OpenRgn

	PushLong #strucRect
	ldy #xowRH	; these are the radii of the corners
	PushWord [<theWindow],y
	ldy #xowRV
	PushWord [<theWindow],y
	_FrameRRect

	ldy #owStrucRgn+2	; push on the handle of the structure
	lda [<theWindow],y	; region stored in the window record.
	sta StrucRgnHandle+2
	pha
	dey
	dey
	lda [<theWindow],y
	sta StrucRgnHandle
	pha
	_CloseRgn

	clc
	rts

ContRgnHandle	ds.b 4
StrucRgnHandle	ds.b 4
TempRgn	ds.b 4

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Fetches the portrect from the window record, and converts it to
; global coordinates. It leaves the rectangle in 'pRect' and 'contRect'
;
; LocalToGlobal conversion is done by subtracting boundsRect.y1 from the
; vertical coordinates of portRect, and doing similarly for the horizontal
; coordinates. This is essentially saying "How far away from the top and
; left edges of the screen is the portRect?".
;

GetpRect	ldy #oport+oboundsRect
	lda [<theWindow],y	;Get the boundsRect y1,x1 and save it in a way
	sta @toglobal	;that allows us to use it conveniently.
	sta @toglobal+4
	iny
	iny
	lda [<theWindow],y
	sta @toglobal+2
	sta @toglobal+6

	ldy #oport+oportRect+6
	ldx #6	;Globalize the portRect and save it where
@a	lda [<theWindow],y	;"others" can get it.
	sec
	sbc @toglobal,x
	sta pRect,x
	sta contRect,x
	dey
	dey
	dex
	dex
	bpl @a

	rts

@toglobal	ds.b	8

	ENDP

	EJECT
*******************************************************************************
*
rrNew	PROC
*
* Description:
*
* Perform any window record initialization. This routine is should set :
*
*   - the wRefCon, wContDraw, wColors, and wFrameCtls fields.
*   - the fCtlTie, fVis, and fQContent bits in wFrame word.
*   - any other fields in the Custom part of the record.
*
* The following has already been done:
*
*   - a window record has been allocated (as specified by the wNew call).
*   - a port has been opened (as specified by the wPosition call).
*   - handles have been placed in wStrucRgn, wContRgn, and wUpdateRgn.
*   - wContDefProc points to us.
*   - the window has been added to the window list, and wNext field set.
*   - the fAllocated and fHilited bits have been set. All others are zero.
*
* Here is the window record. Asterisks are by the fields we have to set up:
*
*	  -4 owNext
*	   0 owPort
*	 170 owDefProc
*	*174 owrRefCon
*	*178 owContDraw
*	 182 owReserved
*	 186 owStrucRgn
*	 190 owContRgn
*	 194 owUpdateRgn
*	 198 owCtls
*	*202 owFrameCtls
*	*206 owFrame
*	*208 owCustom
*
*
* Inputs:	param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:	result = zero
*	carry  = clear
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

;
; Set the frame bits based on the _NewWindow parmlist settings.
;
; We only really pay attention to: fClose, fMove.
;
; In addition, Window manager requires: fVis, fQContent, fCtlTie.
;

	ldy #wFrameBits	; Get the bits from the parm list.
	lda [<param],y	; Make sure we don't affect fAllocated
	and #$FFFF-fAllocated-fHilited ; or fHilited.

	ldy #owFrame	; Get the bits as the WM has them.
	ora [<theWindow],y	; Merge his and ours together...
	sta [<theWindow],y	; ...and save them.

; copy the wRefCon, wContDraw, and wColors from the parmlist

	ldy #owrRefCon	; dest index
	ldx #wRefCon	; source index
	lda #8	; bytes to move
	jsr CopyBlock

; Copy all of the custom stuff into the end of the window record

	ldy #windSize	; used as dest index
	ldx #wCustom	; used as source index
	lda #wEnd-wCustom	; bytes to move
	jsr CopyBlock

; The frame controls are already zeroed out by the Window manager before
; we get called, so we don't have to initialize that field.


; Finally, calculate the Frame and Content regions

	jsr rrCalcRgns

	clc
	rts


CopyBlock
	sta Count
loop
	phy	; save the dest index
	txy	; transfer in the source index
	lda [<param],y	; get a source word
	ply	; retrieve the dest index
	sta [<theWindow],y	; save the copy
	iny	; bump our indices
	iny
	inx
	inx
	dec Count	; are we done?
	dec Count
	bne loop	; no - copy some more

	rts

Count	ds.b 2

	ENDP

	EJECT
*******************************************************************************
*
rrDispose	PROC
*
* Description:	Dispose of any additional fields created by the wNew call,
*	and tell the Window manager whether or not it should
*	continue the disposal. If we return FALSE, the Window
*	Manager will:
*
*	- erase the window from the screen
*	- remove the window from the window list
*	- free any controls in wControls and wFrameCtls
*	- free the strucRgn, contRgn, and updateRgn handles
*	- close the GrafPort
*	- release the window record if it was allocated
*	  dynamically (see allocate bit in wFrame field)
*
*
* Inputs:	NONE
*
* Outputs:	to continue disposal: result = FALSE (zero)
*	to abort disposal:	  result = TRUE  (non-zero)
*	in either case...	  carry  = clear
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

	clc
	rts
	ENDP

	EJECT
*******************************************************************************
*
rrGetDrag	PROC
*
* Description:	Return the address of the routine that will draw the
*	outline of the window as it is dragged. You can take the
*	easy way out and return $0000 0000 in 'result'; that will
*	tell the window manager take care of matters by dragging
*	the bounds rectangle of the strucRgn. I use my own routine
*	which draws a RoundRect.
*
*
* Inputs:	NONE
*
* Outputs:	result = pointer to Drag routine, $0000 0000 for default
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

	lda #myDrag	; return the pointer to my routine
	sta <result
	lda #^myDrag
	sta <result+2

	jsr GetStrucRect	; get a copy of the rect to drag

	lda strucRect	; make a local copy
	sta DragRect
	lda strucRect+2
	sta DragRect+2
	lda strucRect+4
	sta DragRect+4
	lda strucRect+6
	sta DragRect+6

	ldy #xowRV	; get the radii of the corners
	lda [<theWindow],y
	sta localRV

	ldy #xowRH
	lda [<theWindow],y
	sta localRH

	clc
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This drag routine will be called with the following parameters:
;
;	PUSH:WORD - delta X (signed)
;	PUSH:WORD - delta Y (Your truly,)
;	PUSH:BYTE[3] - return address

RTLAddr	equ 1
DY	equ RTLAddr+3
DX	equ DY+2

myDrag
	clc	; offset/copy the original rectangle
	lda DragRect
	adc DY,s
	sta DragRect2

	clc
	lda DragRect+2
	adc DX,s
	sta DragRect2+2

	clc
	lda DragRect+4
	adc DY,s
	sta DragRect2+4

	clc
	lda DragRect+6
	adc DX,s
	sta DragRect2+6

	pha	; save the pen mode
	_GetPenMode

	PushWord #modeXOR	; and change it to XOR
	_SetPenMode

	PushLong #DragRect2
	PushWord localRH
	PushWord localRV
	_FrameRRect

	_SetPenMode	; restore the old pen mode

	lda RTLAddr,s	; move the rtl address back up
	sta 5,s
	lda RTLAddr+1,s
	sta 6,s

	pla	; remove the parameters
	pla

	rtl	; back to dragrect!


DragRect	ds.b 8
DragRect2	ds.b 8
localRH	ds.b 2
localRV	ds.b 2

	ENDP

	EJECT
*******************************************************************************
*
rrGrowFrame	PROC
*
* Description:	Draw the outline of the window frame as it is grown. The
*	easiest way to deal with this routine is to ignore
*	everything passed to it, and return $0000 in result. This
*	will grow windows the normal way.
*
*
* Inputs:	'param' points to the following data structure:
*
*        newsize    RECT  Rectangle that defines the new size
*        drawFlag   WORD  TRUE to draw frame, false to erase
*        startRect  RECT  Bounds of wStrucRgn when dragging started.
*        deltaY     WORD  Vertical movement since starting to drag (signed).
*        deltaX     WORD  Horizontal movement since starting to drag (signed).
*
* Outputs:	'result' should have the following bits set or clear:
*
*        0: TRUE if frame was drawn by us, FALSE if default frame is requested.
*        1: TRUE if newSize RECT was changed in a custom fashion, FALSE if not.
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

newSize 	equ 0
drawFlag	equ newSize+8
startRect	equ drawFlag+2
deltaY	equ startRect+8
deltaX	equ deltaY+2

;
; param is a pointer to a data block, the first 8 bytes of which
; is the rectangle we want to draw. So push Param on the stack for
; FrameRRect.
;
	PushLong <param
	ldy #xowRH
	PushWord [<theWindow],y
	ldy #xowRV
	PushWord [<theWindow],y
	_FrameRRect

	lda #%0001	; say the we drew the rect but
	sta <result	; didn't change it.

	clc
	rts
	ENDP

	EJECT
*******************************************************************************
*
rrRecSize	PROC
*
* Description:	Return the size of the window record required by this
*	defProc. This number is the number of bytes needed beyond
*	the number normally allocated by the window manager.
*
*	If you want to indicate that storage has already been
*	allocated (perhaps a a field was set in the NewWindow
*	parameter list, like wStorage in the standard window list),
*	then return the pointer to that record with bit 31 set.
*
*
* Inputs:	param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:	result = number of additional bytes required, or
*	         pointer to window record with the high bit set
*	carry  = clear
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

; Let's see if there is storage defined in the parameter list

	ldy #wStorage
	lda [<param],y
	iny
	iny
	ora [<param],y
	bne Allocated

; No, so tell the window manager how large it should be

	lda #xowEnd-windSize
	sta <result
	bra done

Allocated
	lda [<param],y	; Return the high word with the high
	ora #$8000	; bit set to tell the WMgr what we did.
	sta <result+2
	dey
	dey
	lda [<param],y	; Return the low word normally
	sta <result

done
	clc
	rts
	ENDP

	EJECT
*******************************************************************************
*
rrPosition	PROC
*
* Description:	Supply the rectangle to be used as the window's PortRect.
*
*
* Inputs:	param  = pointer to parameter list supplied to _NewWindow
*
* Outputs:	result = pointer to the rect to be used as the PortRect
*	carry  = clear
*
* External Refs:
*
* Entry Points:
*
*******************************************************************************
	with RRectDefProcData

; Take the pointer to the parameter list and add the offset to field
; that holds the portrect.

	ADD4 #wPosition,<param,<result

	clc
	rts
	ENDP

	EJECT
*******************************************************************************
*
rrBehind	PROC
*
* Description:	This routine extracts the wPlane value of the parmList
*	passed to NewWindow and passes it back to the Window
*	Manager in 'result'. Pass back $FFFF FFFF to always place
*	the window on top, or $0000 0000 to place the window on the
*	bottom.
*
*
* Inputs:	param  = pointer to parameter list passed to _NewWindow
*
* Outputs:	result = window pointer, $FFFF FFFF, or $0000 0000
*	carry  = clear
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

	ldy #wPlane	; simply get what was specified in
	lda [<param],y	; the parameter list supplied to
	sta <result	; _NewWindow (since we are the only
	iny	; one who knows where is it) and return
	iny	; it to the Window Manager.
	lda [<param],y
	sta <result+2

	clc
	rts
	ENDP

	EJECT
*******************************************************************************
*
rrCallDefProc	PROC
*
* Description:	Generic call to the defProc. Through this, the Window
*	Manager can access the fields in the custom window's
*	record in response to the many Get/Set calls.
*
*
* Inputs:	On entry, 'param' points to the following block of data:
*
*	WORD : dRequest	Requested operation number
*	WORD : paramID	Parameter block type:
*	  	  $0000-7FFF reserved by system
*	  	  $8000-FFFF reserved for application
*		  (We only handle type $0000 System
*		   in this sample)
*	XXXX : newParam	Operation specific data
*
* Outputs:	Call specific. See technote for more details.
*
* External Refs:
	import rrSetTitle
	import rrSetColor
	import rrSetFrame
	import rrGetTitle
	import rrGetColor
	import rrGetFrame
	import handleWTask
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

dRequest	equ 0
paramID	equ dRequest+2
newParam	equ paramID+2

MaxDRequest	equ 33

	ldy #paramID	; Do we know this paramID type?
	lda [<param],y
	bne ignore	; $0000, ignore all others

	lda [<param]	; dRequest
	cmp #MaxDRequest+1	; is this request in range?
	bcs ignore	; no so leave
	asl a	; yes, turn into index into proc table
	tax
	jmp (dRequestTable,x)

dRequestTable
	dc.w ignore	;  0 wSetOrgmask
	dc.w ignore	;  1 wSetMaxGrow
	dc.w ignore	;  2 wSetScroll
	dc.w ignore	;  3 wSetPage
	dc.w ignore	;  4 wSetInfoRefCon
	dc.w ignore	;  5 wSetInfoDraw
	dc.w ignore	;  6 wSetOrigin
	dc.w ignore	;  7 wSetDataSize
	dc.w ignore	;  8 wSetZoomRect
	dc.w rrSetTitle	;  9 wSetTitle
	dc.w rrSetColor	; 10 wSetColorTable
	dc.w rrSetFrame	; 11 wSetFrameFlag
	dc.w ignore	; 12 wGetOrgMask
	dc.w ignore	; 13 wGetMaxGrow
	dc.w ignore	; 14 wGetScroll
	dc.w ignore	; 15 wGetPage
	dc.w ignore	; 16 wGetInfoRefCon
	dc.w ignore	; 17 wGetInfoDraw
	dc.w ignore	; 18 wGetOrigin
	dc.w ignore	; 19 wGetDataSize
	dc.w ignore	; 20 wGetZoomRect
	dc.w rrGetTitle	; 21 wGetTitle
	dc.w rrGetColor	; 22 wGetColorTable
	dc.w rrGetFrame	; 23 wGetFrameFlag
	dc.w ignore	; 24 wGetInfoRect
	dc.w ignore	; 25 wGetDrawInfo
	dc.w ignore	; 26 wGetStartInfoDraw
	dc.w ignore	; 27 wGetEndInfoDraw
	dc.w ignore	; 28 wZoomWindow
	dc.w ignore	; 29 wStartDrawing
	dc.w rrStartMove	; 30 wStartMove (defined in this PROC)
	dc.w ignore	; 31 wStartGrow
	dc.w rrNewSize	; 32 wNewSize (defined in this PROC)
	dc.w handleWTask	; 33 wTask

rrStartMove	ldy #newParam+2	; Preparing to move the window. Examine
	lda [<param],y	; the proposed destination rectangle
	sta <result+2	; and see if it is OK. If it is, simply
	dey	; return it. If it isn't, then change
	dey	; it. We will like it, so we'll just
	lda [<param],y	; return what we get.
	sta <result
	clc
	rts

rrNewSize
	lda #1	; Always return TRUE. This tells the
	sta <result	; window manager to redraw only
	clc	; uncovered contents.
	rts

ignore	clc
	rts

	ENDP

	EJECT
*******************************************************************************
*
handleWTask	PROC
*
* Description:	Called to handle FindWindow results passed on by
*	TaskMaster. Since TaskMaster only handles event that occur
*	in menus and system windows, custom window defprocs must
*	handle all of the rest. These include:
*
*	wInContent	wInDrag
*	wInGrow	wInGoAway
*	wInZoom	wInInfo
*	wInFrame
*
*
* Inputs:	'param' points to the following block of data:
*
*	WORD:dRequest	= 33 for wTask
*	WORD:paramID	we only handle type $0000 System calls
*	LONG:newParam	Pointer to Task Record
*	WORD:newParam	result from FindWindow
*
* Outputs:	'result' equals the following:
*
*		Low Word	High Word
*		-----------------	-------------------
*    If the event was handled:	Zero	Action taken
*    If the event was not handled:	FindWindow result	ignored
*
* External Refs:	NONE
*
* Entry Points:	NONE
*
*******************************************************************************
	with RRectDefProcData

dRequest	equ 0
paramID	equ dRequest+2
newParam	equ paramID+2
TaskRecPtr	equ newParam
FWResult	equ TaskRecPtr+4

TaskRec	equ work

	ldy #TaskRecPtr+2	; get the pointer to the Event Record
	lda [<param],y	; into 'TaskRec', aka 'work'.
	sta <TaskRec+2
	dey
	dey
	lda [<param],y
	sta <TaskRec

	ldy #FWResult	; get the Findwindow result
	lda [<param],y

	sec	; turn it into an index
	sbc #wInContent
	bcc callIgnore	; out of range, so ignore
	cmp #wInFrame-wInContent+1
	bcc doit
callIgnore	lda #wInSpecial-wInContent+1
doit	asl a
	tax
	jmp (wTaskTable,x)

wTaskTable	dc.w doInContent	; doInContent
	dc.w doInDrag	; doInDrag
	dc.w ignoreTask	; doInGrow
	dc.w doInGoAway	; doInGoAway
	dc.w ignoreTask	; doInZoom
	dc.w ignoreTask	; doInInfo
	dc.w ignoreTask	; doInSpecial (default ignore)
	dc.w ignoreTask	; doInDeskItem (not used)
	dc.w doInContent	; doInFrame

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInContent event. Check the TaskMask
; field to see if the application wants us to handle it. If so, bring the
; window to front. Then check to see if the application wants to know what
; we just did. If so, return wInContent. If not, return null.

doInContent
	ldy #owmTaskMask	; do we handle clicks in the content?
	lda [<TaskRec],y
	and #tmContent
	bne Bogus0010	; yes - just select the window
	brl ignoreTask	; no - so pretend we weren't here.

Bogus0010	jsr mySelectWindow

	ldy #owFrame	; do we tell the app what we did?
	lda [<theWindow],y
	and #fQContent
	beq Passively	; no - just return a nullEvt

	ldx #0
	lda #wInContent	; pass this on to the application
	brl Exit
Passively
	ldx #wInContent	; This is what we did.
	lda #0	; Signal that event was handled
	brl Exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInDrag event. Check the TaskMask
; field to see if the application wants us to handle it. If so, call
; DragWindow with the same parameters described in the TaskMaster
; psuedo-code in the ToolBox Reference. Then check to see if the Apple
; key was down. If it wasn't, bring the window forward. Finally, return
; null.
;
doInDrag
	ldy #owmTaskMask	; do we do drags?
	lda [<TaskRec],y
	and #tmDragW
	bne Bogus0020	; yes - get on with it.
	brl ignoreTask	; no - so pretend we weren't here.
Bogus0020
	PushWord #0	; drag resolution
	ldy #owhere+2	; global coord of cursor
	PushWord [<TaskRec],y ; first X
	dey
	dey
	PushWord [<TaskRec],y ; then Y
	PushWord #8	; grace buffer around bounds
	PushLong #0	; default cursor boundary
	ldy #owmTaskData+2	; push on window's grafport
	PushWord [<TaskRec],y
	dey
	dey
	PushWord [<TaskRec],y
	_DragWindow	; Call DrawWindow ourselves

	ldy #omodifiers	; if the Apple Key is down then
	lda [<TaskRec],y	; don't bring the window to front
	and #appleKey
	bne doneDrag

	jsr mySelectWindow
doneDrag
	ldx #wInDrag	; This is what we did.
	lda #0	; Signal that event was handled
	bra Exit	; Exit the DefProc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TaskMaster needs us to handle a wInGoAway event. Check the TaskMask
; field to see if the application wants us to handle it. If so, call
; TrackGoAway. If it returns TRUE, then return wInGoAway to the
; application. If it returns FALSE, return wNoHit.
;
doInGoAway
	pha	; space for boolean result
	ldy #owhere+2	; global coord of cursor
	PushWord [<TaskRec],y ; first X
	dey
	dey
	PushWord [<TaskRec],y ; then Y
	ldy #owmTaskData+2	; push on window's grafport
	PushWord [<TaskRec],y
	dey
	dey
	PushWord [<TaskRec],y
	_TrackGoAway
	pla
	beq noClose

	ldx #0	; Close selected. Tell app that we
	lda #wInGoAway	; clicked in the goAway box.
	bra Exit
noClose
	ldx #wInGoAway	; Close not selected. Tell the app that
	lda #wNoHit	; we tracked it, but that everything is
	bra Exit	; OK now.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Local routine to bring the window forward if we need to.
;
mySelectWindow
	lda <theWindow	; get the pointer to the window so that
	clc	; we can  bring it to front.
	adc #4
	tax
	lda <theWindow+2
	pha
	phx
	_SelectWindow
	rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; For some reason, we need to ignore a task. Either we were asked to handle
; an event we know nothing about, or the TaskMask prohibited us from 
; handling a certain event. This routine simply echos the result found by
; FindWindow back to the application.

ignoreTask	ldy #FWResult	; ignore by echoing the FindWindow
	lda [<param],y	;   result.
	ldx #0	; fall through to Exit.

Exit
	sta <result	; TaskMaster result on the stack
	stx <result+2	; Low word of TaskData

	clc
	rts
	endp

	EJECT
*******************************************************************************
*
HouseKeeping	PROC
*
* Description:	Housekeeping calls. Set and get various fields. These will
*	redraw the window if necessary.
*
*
* Inputs:
*
* Outputs:
*
* External Refs:
	import drawFrame
*
* Entry Points:
	entry rrSetTitle
	entry rrSetColor
	entry rrSetFrame
	entry rrGetTitle
	entry rrGetColor
	entry rrGetFrame
*
*******************************************************************************
	with RRectDefProcData

dRequest	equ 0
paramID	equ dRequest+2
newParam	equ paramID+2


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetTitle	ldy #xowTitle+2
	bra SetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetColor	ldy #xowColorPtr+2
	bra SetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrSetFrame	ldy #owFrame
	bra SetWord

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetTitle	ldy #xowTitle+2
	bra GetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetColor	ldy #xowColorPtr+2
	bra GetLong

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rrGetFrame	ldy #xowColorPtr
	bra GetWord

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetLong
	phy
	ldy #newParam+2
	lda [<param],y
	ply
	sta [<theWindow],y
	dey
	dey
SetWord	phy
	lda #newParam
	lda [<param],y
	ply
	sta [<theWindow],y

	lda <theWindow	; Now redraw the window frame
	clc
	adc #4
	tax
	lda <theWindow+2
	pha
	phx
	_StartFrameDrawing	; must be called by defproc

	jsr drawFrame

	_EndFrameDrawing	; reverses StartFrameDrawing call

	clc
	rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Called by the rrGetxxxxx routines above. Enter with Y holding the
; offset to a LONG parameter in the window record. This routine will
; fetch that value and put it into 'result'.
;

GetLong
	lda [<theWindow],y
	sta <result+2
	dey
	dey
GetWord	lda [<theWindow],y
	sta <result
	clc
	rts
	ENDP