Metropoli BBS
VIEWER: m_init.asm MODE: TEXT (ASCII)
; M_INIT.ASM for E32 - Copyright (C) 1994 Douglas Herr
;  all rights reserved

include	model.inc

public	mouse_init
extrn	cursoron:near
extrn	ismouse:near
extrn	up:near, down:near
extrn	home:near, endd:near
extrn	left:near, right:near
extrn	extended_key:near
extrn	swap_files:near, display_screen:near
extrn	x0:near

include	dataseg.inc
mouse_rc	dw 0
old_left_margin	dw 0
extrn	mouse_on:byte
extrn	cur_posn:byte		; really a word
extrn	first_row:byte
extrn	rows:byte, columns:word
extrn	mouseflag:byte
extrn	normal:byte
extrn	filesel:word
extrn	dirty_bits:byte
extrn	left_margin:word
extrn	filesiz:dword, cursor:dword
@curseg	ends

include	codeseg.inc
mouse_init	proc	near
	call	ismouse
	jnc	short m0
	clc
	ret

; install mouse event handler
m0:
	mov	ax,0
	int	33h

	mov	ax,cs
	mov	es,ax
	lea	edx,mouse_pos
	mov	ax,0Ch
	mov	cx,1010101b
	int	33h

; set horizontal range for cursor
	movzx	edx,columns	; maximum character limit
	mov	cl,3
	cmp	dx,60
	adc	cl,0
	shl	edx,cl
	dec	edx
	xor	ecx,ecx		; minimum
	mov	ax,7
	int	33h

; set vertical range for cursor
	movzx	edx,rows
	inc	edx
;	inc	edx		; allow mouse to point to function key prompts
	mov	cl,3
	shl	edx,cl
	dec	edx
	xor	ecx,ecx
	mov	ax,8
	int	33h
	ret
mouse_init	endp

mouse_pos:
	test	ax,1		; test for mouse motion
	jnz	mp1		; turn mouse on if it moved
	push	fs
	push	ds
	mov	ax,_NEAR
	mov	ds,ax
	assume	ds:_NEAR

	mov	ax,left_margin
	mov	old_left_margin,ax

	mov	fs,filesel
	mov	ax,cx
	mov	cl,3
	shr	dx,cl		; vertical
	cmp	columns,60	; adjust shift factor if 40-column screen
	adc	cl,0
	shr	ax,cl
	xchg	ax,dx
	mov	dh,al

; check to see if the mouse is on the prompt row
	mov	ah,rows
	cmp	dh,ah		; DH > AH?
	ja	prompt

; check for cursor at or above file's first row
	mov	ah,first_row
	dec	ah
	cmp	al,ah
	jb	file_swap
	je	at_top_row

	mov	mouse_rc,dx	; save mouse cursor position

	sub	al,cur_posn+1
	movsx	ecx,al
	or	al,al
	jz	short column
	jns	short go_down
	neg	ecx

	even
go_up:	push	ecx
	call	up
	pop	ecx
	loop	go_up
	jmp	short column

	even
go_down:push	ecx
	call	down
	pop	ecx
	loop	go_down

column:
	movzx	ecx,byte ptr mouse_rc
	movzx	eax,cur_posn
	sub	ecx,eax
	jz	short set_cursor
	js	short mouse_left

; go right as long as the cursor is to the left of the mouse
mouse_right:
	call	right
	mov	eax,cursor
	cmp	eax,filesiz
	jae	short set_cursor
	mov	ax,mouse_rc	; AH = row, AL = column
	cmp	ah,cur_posn+1	; shoud be equal
	je	short mr0
	call	left			; else go back
	jmp	short set_cursor	;  & done
mr0:
	cmp	al,cur_posn	; current column position
	ja	mouse_right
	jmp	short set_cursor

; go left as long as the cursor is to the right of the mouse
mouse_left:
	call	left
	mov	al,byte ptr mouse_rc
	cmp	al,cur_posn
	jb	mouse_left

set_cursor:
; set cursor position
	mov	dx,word ptr cur_posn
	xor	bh,bh
	mov	ah,2
	int	10h

	mov	mouse_on+1,1
	pop	ds
	pop	fs
	assume	DS:nothing
	retf

; turn mouse cursor on if it moved
mp1:	push	ds
	mov	ax,_NEAR
	mov	ds,ax
	assume	ds:_NEAR
	cmp	mouseflag,3
	ja	short mp2
	mov	ax,1
	int	33h
	mov	ds:mouse_on,1	; update flag in E32's data area
mp2:	pop	ds
	retf

;
; switch files if button clicked on inactive file
; operates by stuffing Ctrl-F7 into keyboard buffer
; works OK with GetKey
;
file_swap:
	xor	ecx,ecx
	mov	ch,64h
	mov	ah,5
	int	16h
	pop	ds
	pop	fs
	retf

;
; mouse cursor at file header
; check for cursor at 'R' or 'C'
at_top_row:
	push	es
	push	ds
	pop	es

;	call	mgetchr
;
;	cmp	al,'R'
;	je	short next_row
;	cmp	al,'C'
;	je	short next_column
top_row_exit:
	pop	es
	pop	ds
	pop	fs
	retf

next_row:
	call	down
	jmp	top_row_exit

next_column:
	call	right
	jmp	top_row_exit


shiftkey equ 3
ctrl	equ 4
altb	equ 8

prompt:
	call	mgetchr		; get character & attribute
;	inc	dl
	cmp	ah,normal	; is it in 'Fxx' area?
	jne	short look_for_F
	inc	dl		; right until edge of screen or AH = inverse
	cmp	dl,byte ptr columns
	jb	prompt
too_far_right:
	dec	dl
	call	mgetchr
	cmp	ah,normal
	je	too_far_right

; mouse is in inverse color area
; go left to 'Fxx' prompt
look_for_F:
	dec	dl		; go left
	call	mgetchr
	cmp	ah,normal
	jne	look_for_F

	cmp	al,'0'
	jne	short not_ten
	mov	al,'9'+1
not_ten:
	cmp	al,'1'
	jb	short prompt_key_exit
	add	al,59-'1'

; get shift, Ctrl, Alt-key status
	push	ax
	mov	ax,0200h
	int	16h		; get key toggle status byte
	mov	bl,al
	pop	ax

; test for ALT-key press
	mov	cl,104-59
	test	bl,altb
	jnz	short c

; test for CTRL-key press
	mov	cl,94-59
	test	bl,ctrl
	jnz	short c

; test for SHIFT-key press
	mov	cl,84-59
	test	bl,shiftkey
	jnz	short c

	xor	cx,cx
c:	add	al,cl
	call	extended_key
	jnc	short prompt_key_exit
	jmp	x0

prompt_key_exit:
	mov	dx,word ptr cur_posn
	call	cursoron
	pop	ds
	pop	fs
	retf

mgetchr:
; get character & attribute at mouse cursor position
	push	edx
	mov	ax,word ptr cur_posn
	push	eax
	mov	ah,2		; move cursor to (0,0)
	mov	bh,0		; page 0
	int	10h
	mov	ah,8		; get char and attr
	int	10h
	pop	edx

; save char & attr
; put cursor back where it was
	push	eax
	mov	ah,2
	mov	bh,0
	int	10h
	pop	eax
	pop	edx
	ret

@curseg	ends

	end
[ RETURN TO DIRECTORY ]