
;*****************************************************************************
;
; TTSUBS.ASM
;
; Copyright (C) 1990 by Aaron L. Brenner
;
; Purpose:
;	Subroutines for TICTAC.C
;
; Contents:
;	mouse_init()		Initialize the mouse.
;	mouse_on()		Turns mouse processing on.
;	mouse_off()		Turns mouse processing off.
;	mouse_bounds()		Set the mouse cursor boundaries.
;	mouse_cursor()		Turn the mouse cursor on or off.
;	mouse_buttons()		Get the state of the mouse buttons.
;	mouse_in_region()	Determine whether or not the mouse is in a
;				region.
;
; Revision history:
; 1.00	06/13/90	ALB	Created.
;
;*****************************************************************************

	include	mixed.inc

clang	equ	0

	ifndef	model
model	equ	<small>
	endif

	setmodel

;*****************************************************************************
;
; The mouse_info array gets set by our int handler, and is structured:
;
;*****************************************************************************
mseinfo		struc
 mi_flags	db	?		; Bit flags:
					;  bit 0 = 1	Mouse present
					;  bit 1 = 1	Mouse handling ON
 mi_buttons	db	?		; Button status
 mi_row		db	?		; Current cursor row
 mi_col		db	?		; Current cursor column
mseinfo		ends


;*****************************************************************************
;
; Structure used to define screen regions
;
;*****************************************************************************
REGION		struc
 r_ulrow	db	?		; Upper left row
 r_ulcol	db	?		; Upper left column
 r_lrrow	db	?		; Lower right row
 r_lrcol	db	?		; Lower right column
REGION		ends

	.data
mouse_info	mseinfo<0, 0, 0, 0>

	.code

;*****************************************************************************
;
; This is the user interrupt routine set by Fn 12. All it does is record the
; information passed by the mouse driver.
;
;*****************************************************************************
mse_int		proc	far

	push	ds			; Save it; it's the mouse driver's seg
	mov	ax,DGROUP		; Get our data segment
	mov	ds,ax			;
	test	mouse_info.mi_flags,2	; Should we pay attention?
	jz	msei_exit		; No - ignore this stuff
	mov	mouse_info.mi_buttons,bl; Save the button state
	mov	ax,cx			; Get the column
	mov	cl,3			; Divide row and column by 8
	shr	ax,cl			;  since mse driver reports pixel
	mov	mouse_info.mi_col,al	;  positions instead of text char
	shr	dx,cl			;  positions
	mov	mouse_info.mi_row,dl	; Save the row
msei_exit:
	pop	ds			; Restore their segment
	ret				; Return to mouse driver

mse_int		endp

;*****************************************************************************
;
; int mouse_init(void)
;
; Purpose:
;	Initializes the mouse, setting a user int handler.
;
; Input:
;	None.
;
; Output:
;	Function returns non-zero if there is a mouse.
;
;*****************************************************************************
hproc	mouse_init <uses ax bx cx dx es>

	sub	ax,ax			; Fn 0 - Reset mouse driver
	mov	mouse_info.mi_flags,al	; Clear the flag
	int	33h			;
	or	ax,ax			; Is there a mouse?
	jz	hkms_exit		; Nope - just exit
	and	al,1			; Just use the low bit
	mov	mouse_info.mi_flags,al	; Set the flag saying we have one
	push	cs			; Need segment of the routine
	pop	es			;
	mov	dx,offset mse_int	; Address of routine to call
	mov	cx,0000000000011110b	; Call mask (any button activity)
	mov	ax,12			; Fn 1 - Set user int sub
	int	33h			;
hkms_exit:
	mov	al,mouse_info.mi_flags	; Get the presence flag
	sub	ah,ah			;  to return
	hret				; Return to caller

hendp


;*****************************************************************************
;
; void mouse_on(void)
;
; Purpose:
;	Turn mouse processing on. This turns the mouse cursor on, and tells
;	our int handler to start noticing what the mouse is doing.
;
; Input:
;	None.
;
; Output:
;	Mouse processing is enabled.
;
;*****************************************************************************
hproc	mouse_on <uses ax>

	test	mouse_info.mi_flags,1	; Do we have a mouse?
	jz	mson_exit		; No - never mind
	mov	ax,1			; Turn the cursor on
	int	33h			;
	cli				; Disallow ints for a sec
	or	mouse_info.mi_flags,2	; Enable our processing of mouse
	sti				;
mson_exit:
	hret				; Return to caller

hendp


;*****************************************************************************
;
; void mouse_off(void)
;
; Purpose:
;	Disables further mouse processing.
;
; Input:
;	None.
;
; Output:
;	Mouse processing is disabled, and the mouse cursor is turned off.
;
;*****************************************************************************
hproc	mouse_off <uses ax>

	test	mouse_info.mi_flags,1	; Is there a mouse?
	jz	msof_exit		; No - never mind
	cli				; Disallow these for a sec
	and	mouse_info.mi_flags,not 2; Disable mouse processing
	sti				;
	mov	ax,2			; Turn the cursor off
	int	33h			;
msof_exit:
	hret				; Return to caller

hendp


;*****************************************************************************
;
; void mouse_bounds(int ulrow, int ulcol, int lrrow, int lrcol)
;
; Purpose:
;	Set the bounds for the mouse cursor.
;
; Input:
;	ulrow,
;	ulcol			Row and column for the upper left corner
;	lrrow,
;	lrcol			Row and column for the lower right corner
;
; Output:
;	None. The mouse driver is notified.
;
;*****************************************************************************
hproc	mouse_bounds <uses ax bx cx dx> ulr:word, ulc:word, lrr:word, lrc:word

	test	mouse_info.mi_flags,1	; Is there a mouse?
	jz	msbd_exit		; Nope - exit now
	mov	ax,ulr			; Get upper row
	mov	dx,lrr			;  and lower row
	mov	cl,3			; Gotta multiply by 8 to come out the
	shl	ax,cl			;  way the mouse driver wants
	shl	dx,cl			;
	mov	cx,ax			;
	mov	ax,8			; Set vertical bounds
	int	33h			;
	mov	ax,ulc			; Get left column
	mov	dx,lrc			;   and right column
	mov	cl,3			; Multiply them
	shl	ax,cl			;
	shl	dx,cl			;
	mov	cx,ax			;
	mov	ax,7			; Set horizontal bounds
	int	33h			;
msbd_exit:
	hret				; Return to caller

hendp


;*****************************************************************************
;
; void mouse_cursor(int on_off)
;
; Purpose:
;	Turn the mouse cursor on or off.
;
; Input:
;	on_off			Flag indicating whether the mouse cursor
;				should be turned on or off:
;					on_off = 0	Turn it off
;					on_off != 0	Turn it on
;
; Output:
;	The mouse cursor is on or off, as desired.
;
;*****************************************************************************
hproc	mouse_cursor <uses ax bx> on_off:word

	test	mouse_info.mi_flags,1	; Is there a mouse?
	jz	mscr_exit		; Nope - don't bother
	mov	bx,on_off		; Get the flag value
	mov	ax,1			; Start with ON
	cmp	bx,1			; See if BX = 0 or not
	adc	ax,0			; If BX = 0, then AX = 2 (OFF)
	int	33h			; Call the mouse driver
mscr_exit:
	hret				; Return to caller

hendp


;*****************************************************************************
;
; int mouse_buttons(void)
;
; Purpose:
;	Get the state of the mouse buttons.
;
; Input:
;	None.
;
; Output:
;	Function returns the button state where:
;		bit 0 = 1 if the left button is down
;		bit 1 = 1 if the right button is down
;
;*****************************************************************************
hproc	mouse_buttons

	sub	ax,ax			; Just in case it's early exit
	test	mouse_info.mi_flags,1	; Is there a mouse?
	jz	msbt_exit		; Nope - exit with 0
	mov	al,mouse_info.mi_buttons; Get the button info
	and	al,3			; Just in case
msbt_exit:
	hret				; Return to caller

hendp


;*****************************************************************************
;
; int mouse_in_region(REGION *region_list, int num_regions)
;
; Purpose:
;	Determine whether or not the mouse cursor is in a specific region of
;	the screen.
;
; Input:
;	region_list		Pointer to a list of region structures
;	num_regions		Number of elements in that list
;
; Output:
;	Function returns -1 if the mouse cursor is not in any region, or the
;	index of the region structure.
;
;*****************************************************************************
hproc	mouse_in_region <uses bx cx dx ds> rlist:ptr, rnum:word

	test	mouse_info.mi_flags,1	; Is there a mouse?
	jz	mirg_none		; Nope - return as if not in a region
	mov	cx,rnum			; Get the number of structures
	sub	dx,dx			; Start counter at 0
	mov	ax,word ptr mouse_info.mi_row	; Get the row & column (AL,AH)
	plds	bx,rlist		; Point to the region list
mirg_l1:
	cmp	al,[bx].r_ulrow		; See if we're above it
	jb	mirg_l2			; Yep - not this one
	cmp	al,[bx].r_lrrow		; See if we're below it
	ja	mirg_l2			; Yep - not this one
	cmp	ah,[bx].r_ulcol		; See if we're to the left of it
	jb	mirg_l2			; Yep - not this one
	cmp	ah,[bx].r_lrcol		; See if we're to the right of it
	ja	mirg_l2			; Yep - not this one, period
	mov	ax,dx			; Get index of this one
	jmp	short mirg_exit		; Exit now
mirg_l2:
	add	bx,size REGION		; Point to next one
	inc	dx			; Count it
	loop	mirg_l1			; Loop for all of them
mirg_none:
;
; Not in any region - return -1
;
	mov	ax,-1			; Set return value
mirg_exit:
	hret				; Return to caller

hendp


	end
