Category : Lotus and other Spreadsheets
Archive   : MOUS123.ZIP
Filename : MOUS123.ASM

 
Output of file : MOUS123.ASM contained in archive : MOUS123.ZIP

TITLE - MOUS123: Mouse Interface Front End for Lotus 123
page 60,132
; Initialization calls the following mouse functions:
; RESET mouse(00)
; SET TEXT CURSOR mouse(10)
; SET INT HANDLER mouse(12) : -> mint routine
; echo input to screen until eof
;
;
; EXIT - Clears & resets mouse function (mouse(00)) unless we never initialize
;
; mint - MOUSE INTERRUPT HANDLER : check buttons & location
; Look up associated two byte code for button combination
; For each char to insert, two-byte code in input buffer.
; IF the keyboard buffer is full . . . ignore it!
; -or-
; Calculate change from last position & insert the number of arrows.
;


int_vec segment at 0h ; interrupt vectors
org 51*4 ; mouse interrupt, 51=033h
m_oset dw ? ; if this is zero, NO MOUSE!
m_seg dw ?
int_vec ends


;
bios_data segment at 40h ; DOS data area
org 1ah
buf_head dw ? ; contains offset of next byte in buffer
buf_tail dw ? ; ->past last char in buffer: end
buf_buf dw 16 dup(?) ; buffer: 1 wd= char,scan-code pair
buf_end dw ?
bios_data ends
page
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:CSEG,es:nothing
org 100h
mous123: jmp init ; do setup and initialization

statptr dw w1 ; -> current state parms
statnxt dw w2 ; -> next state parms

; DEFINE FIELDS USED TO TRACK CURSOR
state struc
cursv dw 200/2 ; last vertical pixel loc
cursh dw 640/2 ; last horizontal pixel loc
remv dw 4 ; unaccounted for vert pixels (remainder)
remh dw 0 ; unaccounted horiz pixels (remainder)
vert_ratio dw 8 ; sensitivity, mickeys/byte vertically
horz_ratio dw 40 ; cursor sensitivity horizontally
lbut_ch dw 28*256+13 ; ah=scan code, al=char value
rbut_ch dw 59*256 ; F1 key (char value=0): HELP
both_ch dw 53*256+47 ; switch to other state: '/' or Esc
up_ch dw 72*256 ; cursor up
down_ch dw 80*256 ; cursor down
left_ch dw 75*256 ; cursor left
right_ch dw 77*256 ; cursor right
state ends

; STATE FOR SPREADSHEET ENTRY
w1 state <>
; STATE FOR COMMAND MENU SELECTION
w2 state <8,0,4,0,1000,16,28*256+13,59*256,1*256+27,72*256,80*256,75*256,77*256>


; HANDLE CALLS FROM MOUSE INTERRUPT
; ax : condition mask - what triggered int
; bx = button state: bit0 (left), bit1 (right): 1=down, 0=up
; cx = horizontal cursor position (pixels)
; dx = vertical cursor position (pixels)

mint proc far
push ax ; ax has the condition mask
push bx ; bx for -> status data
push dx ; save dx or it will hurt
push cs ; move cs to ds
pop ds
cmp bx,3 ; are both buttons down?
jne min005 ; no, skip it
or al,02h+08h ; handle interrupt as if both
min005:
mov bx,[statptr] ; -> current status blk
test al,01h ; was call for cursor pos'n?
jz min010 ; no, bypass call
call curs ; cursor changed, handle it
min010:
test al,02h ; was call for both button press?
jz min020 ; no, bypass call
test al,08h ; was call for both button press?
jz min020 ; no, bypass call
call bbut ; both buttons pressed
jmp min040 ; don't call left or right button handlers
min020:
test al,02h ; was call for left button press?
jz min030 ; no, bypass call
call lbut ; left button pressed
min030:
test al,08h ; was call for right button press?
jz min040 ; no, bypass call
call rbut ; right button pressed
min040:
; INTERRUPT EXIT
pop dx ; restore dx or it will hurt
pop bx
pop ax
ret ; interruph handler exit

mint endp
page
; HANDLE CURSOR MOVEMENT
; cx = horizontal cursor position (pixels)
; dx = vertical cursor position (pixels)
; Suppress interrupts to ensure serialization
;
curs proc near
cli ; SUPPRESS INTERRUPTS WHILE I'M MESSING
push ax
push cx ; save horizontal posn
push dx ; save vert pos'n
sub dx,[bx].cursv ; get change in vert pos'n
jz curs50 ; no change
; HOW MANY POSITIONS up or down?
mov ax,dx ; set for division
add ax,[bx].remv ; left-over pixels from last time
cwd ; propagate sign of ax to dx
idiv [bx].vert_ratio ; get # of chars vertically (+ or Ä)
mov [bx].remv,dx ; save left-over pixel count
push cx ; save cx during repeat
mov cx,ax ; quotient, # of chr moved
mov ax,[bx].down_ch ; prime reg: positive => down
cmp cx,0 ; any chrs?
je curs48 ; no chars, skip
jg curs30 ; positive: go use right arrow
neg cx ; abs(cx), make positive
mov ax,[bx].up_ch ; up arrow char
curs30: call iset ; put char into keyboard buffer
loopnz curs30

curs48: pop cx ; restore value from repeating
curs50:
pop dx
mov [bx].cursv,dx ; save vert position for next time

; HANDLE HORIZONTAL POSITION
sub cx,[bx].cursh ; get change in horizontal pos'n
jz curs90 ; no change
; HOW MANY POSITIONS LEFT/RIGHT?
mov ax,cx ; set for division
add ax,[bx].remh ; left-over pixels from last time
cwd ; propagate sign of ax to dx
idiv [bx].horz_ratio ; get # of chars horizontally (+ or Ä)
mov [bx].remh,dx ; save left-over pixel count
mov cx,ax ; quotient, # of chr moved
mov ax,[bx].right_ch ; prime reg: positive => right
cmp cx,0 ; any chrs?
je curs90 ; no chars, skip
jg curs70 ; positive: go use right arrow
neg cx ; abs(cx), make positive
mov ax,[bx].left_ch ; up arrow char
curs70: call iset
loopnz curs70

curs90:
pop cx
mov [bx].cursh,cx ; save horz position for next time

; Make the mouse cursor stay on the screen.

cmp [bx].cursh,640-16 ;is cursor close to the right margin?
jnb curs95 ; out of center, fix
cmp [bx].cursh,16 ; is cursor close to left margin?
jna curs95 ; out of center, fix
cmp [bx].cursv,200-16;is cursor close to the bottom margin?
jnb curs95 ; out of center, fix
cmp [bx].cursv,16 ; is cursor close to the top margin?
ja curs98 ; in bounds, leave it
curs95: ; push cursor back in bounds
mov cx,640/2 ; horizontal center
mov dx,200/2 ; vertical center
mov [bx].cursh,cx ; save horizontal pixel pos'n
mov [bx].cursv,dx ; save vertical pixel pos'n
mov ax,4 ; set cursor position function
int 51 ; call the mouse routine
curs98:
pop ax
sti ; INTERRUPTS BACK ON
ret
curs endp
page


; HANDLE BOTH BUTTONS PRESSED
bbut proc near
push ax
mov ax,[bx].both_ch ; al=0, ah=key #
cli ;HOLD ALL INTERRUPTS
call iset ; stuff the buffer
sti ; INTERRUPTS BACK ON
mov ax,[statnxt] ; -> next status parms
xchg ax,statptr ; swap next & current status parms
mov [statnxt],ax
pop ax
ret
bbut endp


; HANDLE LEFT BUTTON
lbut proc near
push ax
mov ax,[bx].lbut_ch ; al=0, ah= key #
cli ;HOLD ALL INTERRUPTS
call iset ; stuff the buffer
sti ; INTERRUPTS BACK ON
pop ax
ret
lbut endp


; HANDLE RIGHT BUTTON
rbut proc near
push ax
mov ax,[bx].rbut_ch ; al=0, ah= key #
cli ;HOLD ALL INTERRUPTS
call iset ; stuff the buffer
sti ; interrupts ON
pop ax
ret
rbut endp
page
; Stuff ax character into the keyboard buffer

iset proc near
; INTERRUPTS MUST BE OFF DURING THIS ROUTINE.
; IT TWIDDLES SEVERAL UNIQUE LOCATIONS IN LOW STORAGE
; WHICH MUST REMAIN IN SYNCH.
push ax
push bx
push cx
push es
mov cx,bios_data ; set seg for keyboard buffer
mov es,cx
mov bx,es:buf_tail ; ->end of buffer
mov si,bx ; save ptr
inc bx
inc bx ; -> new tail
cmp bx,offset es:buf_end ; check for end of physical buffer
jb iset20 ; jmp not end
mov bx,offset es:buf_buf ; point to physical start of buffer
iset20:
cmp bx,es:buf_head ; has the buffer wrapped??
je isetfl ; yes, beep?
mov es:[si],ax ; store the char
mov es:buf_tail,bx ; reset end of buffer
isetfl: ; buffer full : BEEP?
pop es
pop cx
pop bx
pop ax
ret ; subr exit
iset endp
page
; INITIALIZATION CODE
init:
push ds
mov ax,0
mov ds,ax ; -> interupt vectors
cmp ds:[m_oset],ax ; if both segment &
jnz init05 ;- offset are zero
cmp ds:[m_seg],ax ;- then mouse driver
jnz init05 ;- is not installed!
pop ds ; restablish data seg
mov dx,offset msg02 ; NO MOUSE DRIVER
jmp init08

init05: pop ds ; restablish data seg
mov ax,0 ; initialize mouse rtn
int 51 ; call mouse
cmp ax,0 ; is the mouse there?
jnz init010 ; mouse driver present
; mouse driver NOT present
mov dx,offset msg01 ; -> msg txt
init08: mov ah,9 ; print string function
int 021h ; print it
jmp init999 ; DON'T RESET MOUSE: it isn't there!
;
init010:
mov ax,10 ; set text cursor f'n
mov bx,0 ; type: sfwr cursor
mov cx,0ffffh ; screen mask
mov dx,07700h ; cursor mask (invert character)
int 51 ; call mouse

mov ax,12 ; setup subrtn addr
mov cx,0000bh ; call rtn on: csr moves, button press
mov dx, offset mint ; subroutine addr in ES:DX
int 51 ; call mouse

; MAINLINE: EXECUTE A PROGRAM
;
init100:
mov sp,offset stack+256 ; set up new stack ptr: save space
mov bx,sp ; find endof this pgm
add bx,256+15 ; round up to paragraph
shr bx,1
shr bx,1 ; /16 to get paragraphs
shr bx,1
shr bx,1 ; ES-> seg, BX = new size
mov ah,4ah ; setblock: change segment size
int 21h ; change the size
jnc init110 ; any error?
mov dx,offset msg04 ; setblock failed
jmp init800 ; write msg & quit
page
init110: ; SET UP PARM LIST FOR ATTACH
mov ax,ds:[2ch] ; -> environment from my prefix
mov envptr,ax ; -> environment for new seg
mov ax,offset cmd_lin ; -> new command line
mov cmd_o,ax ; -> cmd line text
mov cmd_s,cs ; seg for text
mov ax,5ch ; offset for FCB @5Ch
mov fcb1_o,ax
mov fcb1_s,cs
mov ax,6ch ; offset for FCB @6Ch
mov fcb2_o,ax
mov fcb2_s,cs
mov bx,offset parm4b; -> parm list
mov dx,offset pgm ; -> pgm name (asciiz: driv:name.ext)
mov ax,4b00h ; ah=4B (f'n), al=0 (load & execute)
int 21h ; ret code in ax
mov dx,offset msg03 ; done msg
mov bx,cs ; f'n 4b DESTROYS the seg regs
mov ss,bx
mov ds,bx
jnc init800 ; write msg & quit

; INVOCATION OF THE PROGRAM FAILED
mov bx,ax ; save reason code
cbw ; set for division
div ten_b
add ax,3030h ; convert to char
mov msg05cd,ax ; stuff into msg
mov dx,offset msg05 ; LOAD & EXECUTE failed
mov ah,9 ; write error msg
int 21h
mov dx,offset msg06 ; msg for invalid f'n
cmp bx,1 ; was it an invalid f'n call?
je init800
mov dx,offset msg07 ; msg for file not found
cmp bx,2 ; was it file not found?
je init800
mov dx,offset msg08 ; msg for access denied
cmp bx,5 ; was it an invalid f'n call?
je init800
mov dx,offset msg09 ; msg for INSUFFICIENT MEMORY
cmp bx,8 ; was it INSUFFICIENT MEMORY?
je init800
mov dx,offset msg10 ; msg for invalid environment
cmp bx,10 ; was it invalid environment?
je init800
mov dx,offset msg11 ; msg for invalid format
cmp bx,11 ; was it invalid format?
jne init900 ; NO? unexpected code.

init800: mov ah,9 ; write error msg & quit
int 21h

init900:
mov ax,0 ; initialize/reset mouse rtn
int 51 ; call mouse
init999: int 020h ; pgm exit
;
;
;
msg01 db 'No mouse hardware. $'
msg02 db 'No mouse driver. $'
msg03 db 'Return from LOAD & EXECUTE.$'
msg04 db 'SETBLOCK failed.$'
msg05 db 'LOAD & EXECUTE FAILED '
msg05cd dw 'xy'
db ' (dec).',13,10,'$'
msg06 db 'Invalid function.$'
msg07 db 'File not found.$'
msg08 db 'Access denied.$'
msg09 db 'Insufficient Memory$.'
msg10 db 'Invalid Environment.$'
msg11 db 'Invalid format.$'

ten_b db 10 ; constant for division
cmd_lin dw 0,0,0,0,0,0,0 ; parameters to be passed (null)
pgm db 'lotus.com',0 ; NAME OF PGM TO EXECUTE (W/ PATH)
dw 0,0,0,0,0,0,0,0,0,0; patch

parm4b: ; parm list used by f'n 4B
envptr dw 0 ; -> environment string for new seg
cmd_o dw 0 ; offset for cmd line
cmd_s dw 0 ; segment for cmd line
fcb1_o dw 0 ; offset & seg for FCB1 @ 5C
fcb1_s dw 0
fcb2_o dw 0 ; offset & seg for FCB2 @ 6C
fcb2_s dw 0

stack dw 10 dup (0) ; low end of stack
cseg ends
end mous123