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



  3 Responses to “Category : Lotus and other Spreadsheets
Archive   : MOUS123.ZIP
Filename : MOUS123.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/