home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
fortran
/
mslang
/
mouse_32
/
mouse.asm
< prev
next >
Wrap
Assembly Source File
|
1993-06-16
|
18KB
|
711 lines
;* MOUSE - Module of mouse functions. To use it, include the MOUSE.FI and
;* MOUSE.FD files in your program. The following functions are public:
;*
;* MOUSEINIT - Initialize mouse
;* GETMOUSEEVENT - Get information about most recent mouse event
;* SETPTRVIS - Set visibility of pointer to HIDE or SHOW
;* SETPTRPOS - Set position of pointer
;* GETPTRPOS - Get pointer position and button status
;*
;* The following structure is defined:
;*
;* EVENT - Defines x, y, and mouse status of a mouse event
;* BTN_STS - Defines x, y, and button status of a mouse button
;*
;* This file illustrates the most important principles of writing
;* assembler routines for 32-bit FORTRAN. These include:
;*
;* - Use .386 and .MODEL flat to set up the appropriate instruction
;* set and segmentation model.
;*
;* - Declare FORTRAN routines with STDCALL attribute. Declare C
;* routines with the C attribute. You can do this globally with
;* .MODEL or individually on each function.
;*
;* - If your routine uses EBX, ESI, or EDI, save the registers at
;* routine entry and restore at exit. You will seldom need to touch
;* segment registers, but if you do, you must save and restore.
;* Do not modify FS or GS.
;*
;* - You can call most DOS and BIOS interrupts. The list of supported
;* interrupts and functions and the method of calling them is similar
;* to that of the DOS Protected Mode Interface (DPMI). A specification
;* for this interface is available from Intel. In summary, functions
;* that do not pass or receive addresses are used exactly the same
;* in 32-bit as in 16-bit. Functions that take segmented addresses
;* in 16-bit take flat addresses in extended registers in 32-bit.
;* For example, a function that passes an address in DS:DX in 16-bit
;* passes an address in EDX in 32-bit.
.386
; Allow fInit, fWait, and WAIT as names instead of instructions
OPTION NOKEYWORD: <fInit fWait WAIT>
.MODEL flat, stdcall
;* Internal information used by various mouse functions.
MOUINFO STRUCT
fExist DWORD 1
fInit DWORD 0
fGraph DWORD 0
xVirtual SWORD 0
yVirtual SWORD 0
xActual SWORD 0
yActual SWORD 0
xLast SWORD 0
yLast SWORD 0
bitBtnLast DWORD 0
cBtn DWORD 0
MOUINFO ENDS
;* Mouse event structure
EVENT STRUCT 4
x SWORD 0
y SWORD 0
bitBtn DWORD 0
EVENT ENDS
;* Mouse button states structure
BTN_STS STRUCT 4
x SWORD 0
y SWORD 0
Btn SWORD 0
BtnState SWORD 0
BTN_STS ENDS
;* Structure for getvideoconfig from FGRAPH.FD
VIDEOCONFIG STRUCT 4
numxpixels SWORD 0 ; number of pixels on X axis
numypixels SWORD 0 ; number of pixels on Y axis
numtextcols SWORD 0 ; number of text columns available
numtextrows SWORD 0 ; number of text rows available
numcolors SWORD 0 ; number of actual colors
bitsperpixel SWORD 0 ; number of bits per pixel
numvideopages SWORD 0 ; number of available video pages
mode SWORD 0 ; current video mode
adapter SWORD 0 ; active display adapter
monitor SWORD 0 ; active display monitor
memory SWORD 0 ; adapter video memory in K bytes
VIDEOCONFIG ENDS
;* Prototype for C function
_getvideoconfig PROTO C vc:PTR VIDEOCONFIG
;* Constants for keyboard function
NO_WAIT EQU 0
WAIT EQU 1
CLEAR_WAIT EQU 2
.DATA
;* Mouse information variable with mouse exist initialized to 1
mi MOUINFO <1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>
.CODE
;* MOUSEINIT - Initialize mouse and turns on mouse pointer. Initializes
;* all internal variables used by other mouse functions. This function
;* should be called whenever a new video mode is set, since internal
;* variables are mode-dependent.
;*
;* Params: none
;*
;* Return: 0 if no mouse available, otherwise number of buttons available
MOUSEINIT PROC USES ebx
LOCAL vc:VIDEOCONFIG
LOCAL pMode:PTR CHAR
; Call graphics function to get configuration information
INVOKE _getvideoconfig,
ADDR vc
mov mi.fInit, 1 ; We have called initialize
sub eax, eax ; Mouse function 0, reset mouse
mov ebx, eax
mov mi.cBtn, eax ; Assume no mouse buttons
int 33h
mov mi.fExist, eax ; Set existence flag for future calls
or ax, ax ; If AX = 0, there is no mouse
jz nomouse
mov mi.cBtn, ebx ; Save number of mouse buttons for return
nomouse:
.IF !mi.fExist
sub eax, eax ; Return 0 if no mouse
ret
.ENDIF
; Set graphics flag.
.IF vc.numxpixels
mov mi.fGraph, 1
mov ax, vc.numypixels
dec ax
mov mi.yActual, ax
mov ax, vc.numxpixels
dec ax
mov mi.xActual, ax
.ELSE
mov mi.fGraph, 0
.ENDIF
; The mouse works on a virtual screen of 640 x pixels by
; (8 * textrows) vertical pixels. By default, it assumes
; 640 x 200 for 25-line mode. You must call function 8 to
; adjust for other screen sizes.
mov mi.xVirtual, 639
.IF mi.fGraph
; mi.yVirtual = vc.numypixels - 1;
mov ax, vc.numypixels
dec ax
mov mi.yVirtual, ax
.ELSE
; mi.yVirtual = (vc.numtextrows SHL 3) - 1;
mov ax, vc.numtextrows
shl ax, 3
dec ax
mov mi.yVirtual, ax
.ENDIF
sub ebx, ebx ; Clear high word
mov eax, 8 ; Set minimum and maximum vertical
sub ecx, ecx ; Minimum is 0
mov dx, mi.yVirtual ; Maximum is 8 * rows (or rows SHL 3)
int 33h ; Adjust for 25, 30, 43, 50, or 60 lines
mov ax, 1 ; Turn on mouse pointer
int 33h
mov ax, 3 ; Get initial position and button status
int 33h
mov mi.xLast, cx ; Save internally
mov mi.yLast, dx
mov mi.bitBtnLast, ebx
mov eax, mi.cBtn ; Return the number of mouse buttons
ret
MOUSEINIT ENDP
;* GETMOUSEEVENT - Check to see if there has been a change in the state since
;* the last call to mouse event. If event occurred, update event structure.
;*
;* Changes detected are: new mouse position and changes in the state of one
;* of the buttons (if a button had been depressed at the time getmouseevent
;* was called and is releasd at the next call, the button state changed).
;*
;* Note: It will NOT detect a button click that happend between calls to
;* getmouseevent; use GetButtonPress instead.
;*
;* Params: pEvent - Pointer to event structure
;*
;* Return: 1 if event, 0 if no event; and may put current position in pEvent
GETMOUSEEVENT PROC USES ebx,
pEvent:PTR EVENT
LOCAL rtn:DWORD
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax ; Return 0
ret
.ENDIF
sub ebx, ebx ; Clear high word
mov ax, 3 ; Get Mouse position and button status
int 33h
sub eax, eax ; Assume no event
cmp cx, mi.xLast ; Has column changed?
jne isevent
cmp dx, mi.yLast ; Has row changed?
jne isevent
cmp ebx, mi.bitBtnLast ; Has button changed?
je noevent
isevent:
mov eax, 1 ; If something changed, event occurred
mov mi.xLast, cx ; Update internal variables
mov mi.yLast, dx
mov mi.bitBtnLast, ebx
noevent:
mov rtn, eax ; Set return value
; If event, put adjusted values in structure.
.IF eax
; If graphics mode, adjust virtual mouse position to actual
; screen coordinates.
.IF mi.fGraph
; pEvent.x = (mi.xLast * mi.xActual) / mi.xVirtual;
sub edx, edx
movzx eax, mi.xLast
movzx ecx, mi.xActual
mul ecx
movzx ecx, mi.xVirtual
div ecx
mov ecx, pEvent
mov (EVENT PTR [ecx]).x, ax
; pEvent.y = (mi.yLast * mi.yActual) / mi.yVirtual;
movzx eax, mi.yLast
movzx ecx, mi.yActual
mul ecx
movzx ecx, mi.yVirtual
div ecx
mov ecx, pEvent
mov [ecx].EVENT.y, ax
; If text mode, adjust virtual mouse position to 1-based
; row/column.
.ELSE
; pEvent.x = (mi.xLast SHR 3) + 1;
movzx eax, mi.xLast
shr eax, 3
inc eax
mov ecx, pEvent
mov [ecx].EVENT.x, ax
; pEvent.y = (mi.yLast SHR 3) + 1;
movzx eax, mi.yLast
shr eax, 3
inc eax
mov ecx, pEvent
mov [ecx].EVENT.y, ax
.ENDIF
; pEvent.bitBtn = mi.bitBtnLast;
mov eax, mi.bitBtnLast
mov [ecx].EVENT.bitBtn, eax
.ENDIF
mov eax, rtn
ret
GETMOUSEEVENT ENDP
;* GETPTRPOS - Get mouse pointer position and button status regardless of
;* whether there was an event.
;*
;* Params: pEvent - Pointer to event structure
;*
;* Return: 0 if no mouse, otherwise 1 (ignored by FORTRAN)
GETPTRPOS PROC USES ebx,
pEvent:PTR EVENT
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax
ret
.ENDIF
sub ebx, ebx ; Clear upper word
mov ax, 3 ; Get Mouse position and button status
int 33h
mov eax, pEvent
mov (EVENT PTR [eax]).x, cx
mov (EVENT PTR [eax]).y, dx
mov (EVENT PTR [eax]).bitBtn, ebx
; If graphics mode, adjust virtual mouse position to actual
; screen coordinates.
.IF mi.fGraph
; pEvent.x = (pEvent.x * mi.xActual) / mi.xVirtual;
sub edx, edx
mov ecx, pEvent
movzx ecx, (EVENT PTR [ecx]).x
movzx eax, mi.xActual
mul ecx
movzx ecx, mi.xVirtual
div ecx
mov ecx, pEvent
mov (EVENT PTR [ecx]).x, ax
; pEvent.y = (pEvent.y * mi.yActual) / mi.yVirtual;
mov ecx, pEvent
movzx ecx, (EVENT PTR [ecx]).y
movzx eax, mi.yActual
mul ecx
movzx ecx, mi.yVirtual
div ecx
mov ecx, pEvent
mov [ecx].EVENT.y, ax
; If text mode, adjust virtual mouse position to 1-based
; row/column.
.ELSE
; pEvent.x = pEvent.x SHR 3
; pEvent.x = pEvent.x + 1
mov ecx, pEvent
movzx eax, (EVENT PTR pEvent[ecx]).x
shr eax, 3
inc eax
mov (EVENT PTR pEvent[ecx]).x, ax
; pEvent.y = pEvent.y SHR 3
; pEvent.y = pEvent.y + 1
movzx eax, (EVENT PTR pEvent[ecx]).y
shr eax, 3
inc eax
mov (EVENT PTR pEvent[ecx]).y, ax
.ENDIF
mov eax, 1
ret
GETPTRPOS ENDP
;* SETPTRPOS - Set mouse pointer position.
;*
;* Params: x - column position in text modes, actual x coordinate in graphics
;* y - row position in text modes, actual y coordinate in graphics
;*
;* Return: 0 if no mouse, otherwise 1 (ignored by FORTRAN)
SETPTRPOS PROC,
x:DWORD,
y:DWORD
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax
ret
.ENDIF
; If graphics, adjust actual coordinates to virtual coordinates.
.IF mi.fGraph
; x = (x * mi.xActual) / mi.xVirtual;
sub edx, edx
movzx eax, mi.xActual
mul x
movzx ecx, mi.xVirtual
div ecx
mov x, eax
; y = (y * mi.yActual) / mi.yVirtual;
movzx eax, mi.yActual
mul y
movzx ecx, mi.yVirtual
div ecx
mov y, eax
; If text, adjust row/column to 0-based virtual coordinates.
.ELSE
; x = x - 1
; x = x SHL 3
dec x
shl x, 3
; y = y - 1
; y = x SHL 3
dec y
shl y, 3
.ENDIF
mov ax, 4 ; Set mouse position
mov ecx, x
mov edx, y
int 33h
mov eax, 1
ret
SETPTRPOS ENDP
;* GETBUTTONPRESS - Get button press status and mouse pointer position at the
;* time the button was last pressed.
;*
;* Params: btns - Pointer to button states structure
;* btns.Btn - select button: left 0, right 1, middle 2 (if any)
;*
;* Return: 0 if no mouse, otherwise number of button presses for selected button
;* since last call to GETBUTTONPRESS
;* btns.x,btns.y - is the position of the last button press
;* btns.BtnState
GETBUTTONPRESS PROC USES ebx,
btns:PTR BTN_STS
LOCAL rtn:DWORD
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax
ret
.ENDIF
mov eax, btns
movzx ebx, [eax].BTN_STS.Btn ;select button
mov ax, 5 ; Get selected button's press status and position
int 33h
mov rtn, ebx ; Set return value (number of times button pressed)
mov ebx, btns
mov [ebx].BTN_STS.x, cx ; position of last button press
mov [ebx].BTN_STS.y, dx
mov [ebx].BTN_STS.BtnState, ax
mov [ebx].BTN_STS.y, dx
; If graphics mode, adjust virtual mouse position to actual
; screen coordinates.
.IF mi.fGraph
; btns.x = (btns.x * mi.xActual) / mi.xVirtual;
sub edx, edx
mov ecx, btns
movzx ecx, [ecx].BTN_STS.x
movzx eax, mi.xActual
mul ecx
movzx ecx, mi.xVirtual
div ecx
mov ecx, btns
mov [ecx].BTN_STS.x, ax
; btns.y = (btns.y * mi.yActual) / mi.yVirtual;
mov ecx, btns
movzx ecx, [ecx].BTN_STS.y
movzx eax, mi.yActual
mul ecx
movzx ecx, mi.yVirtual
div ecx
mov ecx, btns
mov [ecx].BTN_STS.y, ax
; If text mode, adjust virtual mouse position to 1-based
; row/column.
.ELSE
; btns.x = btns.x SHR 3
; btns.x = btns.x + 1
mov ecx, btns
movzx eax, [ecx].BTN_STS.x
shr eax, 3
inc eax
mov [ecx].BTN_STS.x, ax
; btns.y = btns.y SHR 3
; btns.y = btns.y + 1
movzx eax, [ecx].BTN_STS.y
shr eax, 3
inc eax
mov [ecx].BTN_STS.y, ax
.ENDIF
mov eax, rtn
ret
GETBUTTONPRESS ENDP
;* GETBUTTONRELEASE - Get button release status and mouse pointer position at the
;* time the button was last released.
;*
;* Params: btns - Pointer to button states structure
;* btns.Btn - select button: left 0, right 1, middle 2 (if any)
;*
;* Return: 0 if no mouse, otherwise number of button releases for selected button
;* since last call to GETBUTTONRELEASE
;* btns.x,btns.y - is the position of the last button release
;* btns.BtnState
GETBUTTONRELEASE PROC USES ebx,
btns:PTR BTN_STS
LOCAL rtn:DWORD
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax
ret
.ENDIF
mov eax, btns
movzx ebx, [eax].BTN_STS.Btn ;select button
mov ax, 6 ; Get selected button's release status and position
int 33h
mov rtn, ebx ; Set return value (number of times button released)
mov ebx, btns
mov [ebx].BTN_STS.x, cx ; position of last button release
mov [ebx].BTN_STS.y, dx
mov [ebx].BTN_STS.BtnState, ax
mov [ebx].BTN_STS.y, dx
; If graphics mode, adjust virtual mouse position to actual
; screen coordinates.
.IF mi.fGraph
; btns.x = (btns.x * mi.xActual) / mi.xVirtual;
sub edx, edx
mov ecx, btns
movzx ecx, [ecx].BTN_STS.x
movzx eax, mi.xActual
mul ecx
movzx ecx, mi.xVirtual
div ecx
mov ecx, btns
mov [ecx].BTN_STS.x, ax
; btns.y = (btns.y * mi.yActual) / mi.yVirtual;
mov ecx, btns
movzx ecx, [ecx].BTN_STS.y
movzx eax, mi.yActual
mul ecx
movzx ecx, mi.yVirtual
div ecx
mov ecx, btns
mov [ecx].BTN_STS.y, ax
; If text mode, adjust virtual mouse position to 1-based
; row/column.
.ELSE
; btns.x = btns.x SHR 3
; btns.x = btns.x + 1
mov ecx, btns
movzx eax, [ecx].BTN_STS.x
shr eax, 3
inc eax
mov [ecx].BTN_STS.x, ax
; btns.y = btns.y SHR 3
; btns.y = btns.y + 1
movzx eax, [ecx].BTN_STS.y
shr eax, 3
inc eax
mov [ecx].BTN_STS.y, ax
.ENDIF
mov eax, rtn
ret
GETBUTTONRELEASE ENDP
;* SETPTRVIS - Set pointer visibility.
;*
;* Params: state - SHOW or HIDE
;*
;* Return: 0 if no mouse or invalid range, otherwise 1 (ignored by FORTRAN)
SETPTRVIS PROC,
pv:DWORD
; Make sure that mouse is initialized and exists.
.IF !mi.fInit
INVOKE MOUSEINIT
.ENDIF
.IF !mi.fExist
sub eax, eax
ret
.ENDIF
mov eax, pv ; Show or hide mouse pointer
cmp eax, 1
jb EExit
cmp eax, 2
ja EExit
int 33h
mov eax, 1
Exit:
ret
EExit:
sub eax, eax
jmp Exit
SETPTRVIS ENDP
END