home *** CD-ROM | disk | FTP | other *** search
- ;* 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
-
-