; v22.0201.002, Fall 1997, Yap
TITLE hw4_mse1.asm: My_Editor with Mouse + Mouse Interrupt
; Modification of hw4 solution of Kifer,Saad,Pignataro's team
;	by adding mouse functions.
; BUGS: does not work on WinNT environment?
; TO DO: use Alt+F7 to trace into the INT 33h
;	so see what is going on.
; TASM: tasm hw4_mse1+hw4a+hw4b
;
IF1
  include mymacros.lib    ; macro library
ENDIF
;
;
; PROCEDURES
  extrn filesave : near,get_name:near,file_name:byte
  extrn restore_pos : near, store_pos : near, cursor_status : near
  extrn append : near
;
;
.MODEL small
.386
.STACK 100h
;
.DATA
F1      EQU     3Bh
F2      EQU     3Ch
F3      EQU     3Dh
F4	  EQU	    3Eh
;
.CODE
;
MAIN PROC
  init_ds         ; macro to initialize data segment
;---------
; append (insert) mode is default
  save_regs <ax, es, di>         ;macro to save registers

  xor cx,cx                      
  mov ax, 0040h
  mov es, ax
  mov di, 0017h
  or es:byte ptr [di], 80h             ; bit 7 on = 10000000 = insert toggle

  restore_regs <di, es, ax>
;---------

; set video mode
  xor ah, ah        
  mov al, 3       ; set to video mode 3, 80x25
  int 10h
 

; move cursor
  mov ah, 2        
  xor dx, dx      ; dx = 0
  xor bh, bh      ; bh = 0
  int 10h         ; move cursor to 0,0

; mse init
	call init_mse
; install interrupt
	call mse_int

; get keystroke
  xor ah, ah
  int 16h

while_:

; AH has scan code, AL has ascii char
  cmp ah, 1h            ; if escape then end prog.
  je end_while

 
; if function key      
  
  cmp al, 0       ; if a key has been pressed then check
		  ; toggle
  jne else_

then:
  call do_function
  jmp next_key
else_:
  mov dl, al            ; save character

  mov ah, 2             ; get keyboard flags
  int 16h
  test al, 80h

  je resume       ; is toggle key off? then just display
  call append     ; else insert characters

resume:
  mov ah, 2       ; display key pressed
		  ; DL already has character
  int 21h
	
  jmp next_key
next_key:       
  mov ah,0
  int 16h
  jmp while_

end_while:
  Dos_rtn
MAIN ENDP

;==========================================================
; procedures
;
do_function proc
  save_regs <bx, cx, dx, ax>

  mov ah, 3             ; get cursor position and size
			; DH = row, DL = column
  mov bh, 0     
  int 10h

  pop ax  ; retrieves scan code

;case of
  cmp ah, 72       ; uparrow?
  je cursor_up

  cmp ah, 75       ; left arrow?
  je cursor_left

  cmp ah, 77       ; right arrow?
  je cursor_right

  cmp ah, 80       ; down arrow?
  je cursor_down

  



  cmp ah, 52h           ; was INS key hit?
  je   cursorchk       

  cmp ah, F1            ; was F1 key hit? save position.
  je store

  cmp ah, F2            ; was F2 hit? restore position.
  je restore

  cmp ah, F3            ; was F3 hit? save screen to file.
  je savefile

  cmp ah, F4		; new: F4 hit? move cursor to mse pointer
  je jmp_2_mse

  jmp exit
	
cursor_up:
	cmp dh,0        ; row 0?
	je scroll_down
	dec dh          ; no, row=row-1
	jmp execute
cursor_down:
	cmp dh,24       ; last row?
	je scroll_up    
	inc dh          ;no, row :=+1
	jmp execute
cursor_left:
	cmp dl,0        ; col 0?
	jne go_left

	cmp dh,0        ; row 0?
	je scroll_down
	dec dh          ; row =- 1
	mov dl,79
	jmp execute
cursor_right:
	cmp dl,79       ;last col?
	jne go_right
	cmp dh,24       ;last row?
	je scroll_up
	inc dh          ;row=+1
	mov dl,0
	jmp execute
go_left:
	dec dl          ;move cursor back one column
	jmp execute
go_right:
	inc dl          ;advance cursor one column
	jmp execute
scroll_down:
	mov al,1        ;number of lines to scroll
	xor cx,cx       ;set row and column of upper left corner to 0
	mov dh,24       ;set row of lower right corner to 24
	mov dl,79       ;set column of lower left corner to 79
	mov bh,7        ;attribute of blank lines
	mov ah,7
	int 10h         ;execute scroll
	jmp  exit
scroll_up:
	mov al,1        ;number of lines to scroll
	xor cx,cx       ;set row and column of upper left corner to 0
	mov dx,184fh    ;set row and column of lower left corner 
	mov bh,7        ;attribute of blank lines
	mov ah,6
	int 10h         ;execute scroll
	jmp exit



cursorchk:
  call cursor_status    ; determines the cursor in respect to INS key
jmp exit

store:
  call store_pos        ; store current position of cursor
jmp exit

restore:
  call restore_pos      ; then restore cursor position
jmp exit

savefile:
  call get_name
  call filesave
jmp exit

jmp_2_mse:
  call mov_2_mse
jmp exit

execute:
  mov ah,2
  int 10h
exit:

  restore_regs <dx, cx, bx>
  ret
do_function endp

init_mse proc
	mov ax,0        ;fn=init mse
	int 33h
	cmp ax,0        ;mse installed?
	je no_mse
	mov ax,1        ;show mse ptr
	int 33h
  no_mse:
	ret
init_mse endp

mov_2_mse proc
; this is called by the mouse interrupt function,
; so CX,DX are already setup, and the following is not needed.
;	mov ax,3	;fn=get mse ptr location
;	int 33h
	pusha
	shr cx,3	;div by 8 to get cursor pos
	shr dx,3
	push dx
	mov dl,cl	;dl is tne new cursor col (0-79)
	pop cx
	mov dh,cl	;dh is the new cursor row (0-24)
	xor bh,bh	;page 0
	mov ah,2	;fn=move cursor
	int 10h
	popa
	iret
mov_2_mse endp

mse_int proc
	mov ax,seg mov_2_mse
	mov es,ax
	lea dx,mov_2_mse		; new mse interrupt handler
	xor ch,ch			; CX=event mask
	mov cl,00010100b		; set up for left and right button release events
	mov ax,0ch			; fn=install new mse handler
	int 33h
	ret
mse_int endp
end main
