wct@po.CWRU.Edu (William C. Thompson) (04/17/91)
Here's a long awaited mouse unit... UNIT Mouse; { Mouse unit for Turbo Pascal. The comments in this unit were basically copied directly from the Advanced MS Dos Programing book, the section on the Microsoft Mouse Driver, which was the source of all the mouse interrupt functions and their parameters. } INTERFACE USES Dos; CONST LeftButton = 1; RightButton = 2; CenterButton = 4; AnyButton = 7; PROCEDURE InitMouse(VAR Buttons : word; VAR Err : boolean); { Initializes the mouse driver. Call: nothing Returns: Buttons = number of mouse buttons Err = false if mouse support is available, true otherwise Note: * After a call to this function the driver is initialized to the following state: - Mouse pointer at screen center and hidden. - Display page is set to zero. - Mouse pointer shape set to default arrow shape in graphics modes, or reverse block in text modes. - User mouse event handlers are disabled. - Light pen emulation enabled. - Mouse sensitivity set to default vales (see SetMouseSense) - Pointer limits set to entire screen. } PROCEDURE ShowPointer; { Displays the mouse pointer, and cancels any pointer exclusion area. Call: nothing Returns: nothing Note: * A counter is maintained which is decremented by HidePointer and is incremented (if nonzero) by this function. The mouse pointer is displayed any time the counter is zero. The counter is set to -1 when the mouse driver is reset. } PROCEDURE HidePointer; { Removes the mouse pointer from the screen, but continues to track the position of the mouse. Call: nothing Returns: nothing Note: * see ShowPointer } FUNCTION ButtonPressed(Mask : word) : boolean; { Returns a true value if the specified button(s) is pressed. Call: Mask = bit mask of desired button(s) bit(s) Significance(if set) 0 left button 1 right button 2 center button 3-15 reserved(0) Returns: True is button is pressed, false otherwise. Note: * The constants LeftButton, RightButton, CenterButton, and AnyButton can be used for the bit masking. They equal 1, 2, 4, and 7 respectivly. } PROCEDURE GetMousePosition(VAR Buttons, Horiz, Vert : word); { Returns the current mouse button status and pointer position. Call: nothing Returns: Buttons = mouse button status Horiz = horizontal (X) coordinate Vert = vertical (Y) coordinate Note: * Coordinates are in pixels regardless of the current display mode. Position (0,0) is the upper left corner of the screen. } FUNCTION MouseIn(x1,y1,x2,y2: word):boolean; { Returns true if mouse is within rectangle with upper-left corner (x1,y1) and lower-right corner (x2,y2). } PROCEDURE SetPointerPosition(Horiz, Vert : word); { Set the position of the pointer. The pointer is displayed in the new position unless it has been hidden using HidePointer or it is an exclusion area defined by SetPointerExcl. Call: Horiz = horizontal (X) coordinate Vert = vertical (Y) coordinate Returns: nothing Notes: * Coordinates are in pixels regardless of the current display mode. Position (0,0) is the upper left corner of the screen. * The position is adjusted if necessary to lie within the pointer limits set by SetLimits. } PROCEDURE GetPressInfo(Button : word; VAR Stat, Count, Horiz, Vert : word); { Returns the current status of all mouse buttons, and the number of presses and position of the last press for a specifed mouse button since the last call to this procedure for that button. The press counter for the button is reset to zero. Call: Button = button identifier 0 = left button 1 = right button 2 = center button Returns: Stat = button status bit(s) Significance(if set) 0 left button is down 1 right button is down 2 center button is down 3-15 reserved(0) Count = button press counter Horiz = horizontal (X) coordinate of last button press Vert = vertical (Y) coordinate of last button press } PROCEDURE GetReleaseInfo(Button : word; VAR Stat, Count, Horiz, Vert : word); { Returns the current status of all mouse buttons, and the number of releases and position of the last release for a specifed mouse button since the last call to this procedure for that button. The release counter for the button is reset to zero. Call: Button = button identifier 0 = left button 1 = right button 2 = center button Returns: Stat = button status bit(s) Significance(if set) 0 left button is down 1 right button is down 2 center button is down 3-15 reserved(0) Count = button release counter Horiz = horizontal (X) coordinate of last button release Vert = vertical (Y) coordinate of last button release } PROCEDURE SetLimits(HorMin, HorMax, VerMin, VerMax : word); { Limits the mouse pointer to stay within a certian area. Call: HorMin = Minimum horizontal (X) coordinate HorMax = Maximum horizontal (X) coordinate VerMin = Minimum vertical (Y) coordinate VerMax = Maximum vertical (Y) coordinate Returns: nothing Note: * If both HorMin and HorMax are zero then then the previous horizontal limits remain unchanged; the same is true for VerMin and VerMax. } PROCEDURE SetPointerShape(Horiz, Vert : word; Buffer : pointer); { Defines the shape, color, and hot spot of the pointer in graphics modes. Call: Horiz = hot spot offset from the left Vert = hot spot offset from the top Buffer = pointer to mouse pointer image buffer Returns: nothing Note: * The pointer image buffer is 64 bytes long. The first 32 bytes contain a bit mask which is ANDed with the screen image, and the remaining 32 bytes are then XORed with the screen image. * The hot spot is relative to the upper left corner of the pointer image, and each offset must be in the range -16 to 16. In display modes 4 and 5, the horizontal offset must be an even number. } PROCEDURE SetTextPointer(PtrTyp, AND_Str, XOR_End : word); { Defines the shape and attributes of the mouse pointer in text modes. Call: PtrTyp = pointer type 0 = software cursor 1 = hardware cursor AND_Str = AND mask value (if PtrTyp = 0) or starting line for cursor (if PtrTyp = 1) XOR_End = XOR mask value (if PtrTyp = 0) or ending line for cursor (if PtrTyp = 1) Returns: nothing Notes: * If the software text cursor is selected, the masks in AND_Str and XOR_End are mapped as follows: Bit(s) Significance 0-7 character code 8-10 foreground color 11 intensity 12-14 background color 15 blink For Example, the following call would yeild a software cursor that inverts the foreground and background colors: SetTextPointer(0, $77FF, $7700); * When the hardware text cursor is selected, the values in AND_Str and XOR_End are the starting and ending lines for the blinking cursor generated by the video adapter. The maximum scan line depends on the type of adapter and the current display mode. } PROCEDURE GetMotionCount(VAR Horiz, Vert : word); { Returns the net mouse displacement since the last call to this procedure. The returned value is in mickeys; a positive number indicates travel to the right or downwards, a negative number indicates travel to the left or upwards. One mickey represents approximately 1/200 of an inch of mouse movement. Call: nothing Returns: Horiz = horizontal (X) mickey count Vert = vertical (Y) mickey count } PROCEDURE SetEventHandler(EventMask : word; Handler : pointer); { Sets the address and event mask for an application program's mouse event handler. The handler is called by the mouse drvier whenever the specifed mouse events occur. Call: EventMask = event mask Bit(s) Significance(if set) 0 mouse movement 1 left button pressed 2 left button released 3 right button pressed 4 right button released 5 center button pressed 6 center button released 7-15 reserved(0) Handler = Pointer to the handler procedure Returns: nothing Notes: * The user-defined handler is entered from the mouse driver by a far call with the registers set up as follows: AX mouse event flags (see event mask) BX button state Bit(s) Significance(if set) 0 left button is down 1 right button is down 2 center button is down 3-15 reserved(0) CX horizontal (X) pointer coordinate DX vertical (Y) pointer coordinate SI last raw vertical mickey count DI last raw horizontal mickey count DS mouse driver data segment * If an event does not generate a call to the user-defined handler because its bit is not set in the event mask, it is still reported in the event falgs during calls to the handler for events which are enabled. } PROCEDURE SetLightPen(On_Off : word); { Turns the light pen emulation by the mouse driver for IBM BASIC on or off. A "pen down" condition is created by pressing the left and right mouse buttons simultaneosly. Call: On_Off = true to enable or false to disable emulation. Returns: nothing } PROCEDURE SetPointerExcl(HorMin, VerMin, HorMax, VerMax : word); { Defines an exclusion area for the mouse pointer. When the mouse pointer lies within the specified area, it is not displayed. Call: HorMin = upper left X coordinate VerMin = upper left Y coordinate HorMax = lower right X coordinate VerMax = lower right Y coordinate Returns: nothing Note: * The exclusion area is replaced by another call to this procdure or cancelled by InitMouse and ShowPointer. } PROCEDURE SwapEventHandlers(VAR Mask : word; VAR Buffer : pointer); { Set the address and event mask for an application program's mouse event handler and returns the address and event mask for the previous handler. The newly installed handler is called by the mouse driver whenever the specified mouse events occur. Call: Mask = event mask Bit(s) Significance(if set) 0 mouse movement 1 left button pressed 2 left button released 3 right button pressed 4 right button released 5 center button pressed 6 center button released 7-15 reserved(0) Handler = Pointer to the handler procedure Returns: Mask = previous event mask Handler = pointer to previous handler Notes: * The notes for SetEventHandler describe the information passed to the user-defined event handler. Also see SetAltEventHandler. * Calls to the event handler are disabled with InitMouse or by setting an event mask of zero. } FUNCTION GetSaveStateSize : word; { Returns the size of the buffer required to store the current state of the mouse driver. Note: * also see SaveDrvrState and RestoreDrvrState. } PROCEDURE SaveDrvrState(Buffer : pointer); { Saves the mouse driver state in a user buffer. THe minimum size for the buffer must be determined by GetSaveStateSize. Call: Buffer = pointer to the user defined buffer. Returns: nothing Note: * Use this procedure before executing a child program (Exec), in case the child aslo uses the mouse. After the Exec call, restore the previous mouse driver state using RestoreDrvrState. } PROCEDURE RestoreDrvrState(Buffer : pointer); { Restores the mouse driver state from a user buffer. Call: Buffer = pointer to the user defined buffer. Returns: nothing Note: * The mouse driver state must have been previously saved into the same buffer with SaveDrvrState. The format of the data in the buffer in undocumented and subject to change. } PROCEDURE SetAltEventHandler(Mask : word; Handler : pointer; VAR Err: boolean); { Sets the address and event mask for an application program's mouse event handler. As many as three handlers with distinct event masks can be registered with this function. When an event occurs that matches one of the masks, the corresponding handler is called by the mouse driver. Call: Mask = event mask Bit(s) Significance(if set) 0 mouse movement 1 left button pressed 2 left button released 3 right button pressed 4 right button released 5 Shift key pressed during button press or release 6 Ctrl key pressed during button press or release 7 Alt key pressed during button press or release 8-15 reserved(0) Handler = Pointer to the handler procedure Returns: Err = false if successful, true otherwise Notes: * When this procedure is called, at least one of the bits 5, 6, and 7 must be set in Mask. * The user-defined handler is entered from the mouse driver by a far call with the registers set up as follows: AX mouse event flags (see event mask) BX button state Bit(s) Significance(if set) 0 left button is down 1 right button is down 2 center button is down 3-15 reserved(0) CX horizontal (X) pointer coordinate DX vertical (Y) pointer coordinate SI last raw vertical mickey count DI last raw horizontal mickey count DS mouse driver data segment * If an event does not generate a call to the user-defined handler because its bit is not set in the event mask, it is still reported in the event falgs during calls to the handler for events which are enabled. * Calls to the handler are disabled with InitMouse. * Also see SetEventHandler and SwapEventHandlers. } PROCEDURE GetAltEventAdrs(VAR Mask : word; VAR Handler : pointer; VAR Err : boolean); { Returns the address for the mouse event handler matching the specified event mask. Call: Mask = event mask (see SetAltEventHandler) Returns: Mask = event mask Handler = pointer to the alternate event handler Err = false if successful, true if not successful (no handler installed or event mask does not match any installed handler. Note: * SetAltEventHandler allows as many as three event handler with distinct event masks to be installed. This procedure can be called to search for a handler that matches a specific event, so that it can be replaced or disabled. } PROCEDURE SetMouseSense(Horiz, Vert, Double : word); { Set the number of mickeys per 8 pixels for horizontal and vertical mouse motion and the threshold speed for doubleing pointer motion on the screen. One mickey represents approximately 1/200 of an inch of mouse travel. Call: Horiz = horizontal mickeys (1-32,767; default=8) Vert = vertical mickeys (1-32,767; default=16) Double = double speed threshold in mickeys/second (default=64); Returns: nothing } PROCEDURE GetMouseSense(VAR Horiz, Vert, Double : word); { Return the current mickeys to pixels ratios for vertical and horizontal screen movement and the threshold speed for doubling of pointer motion. Call: nothing Returns: Horiz = horizontal mickeys (1-32,767; default=8) Vert = vertical mickeys (1-32,767; default=16) Double = double speed threshold in mickeys/second (default=64); } PROCEDURE SetMouseIntr(Flags : word); { Sets the rate at which the mouse driver polls the status of the mouse. Faster rates provide better resolution in graphics mode but may degrade the performance of application programs. Call: Flags = interrupt rate flags Bit(s) Significance(if set) 0 no interrupts allowed 1 30 interrupts/second 2 50 interrupts/second 3 100 interrupts/second 4 200 interrupts/second 5-15 reserved(0) Returns: nothing Notes: * This procedure is applicable for the InPort Mouse only. * In more than one bit is set in Flags, the lowest order bit prevails. } PROCEDURE SetPointerPage(Page : word); { Selects the display page for the mouse pointer. Call: Page = display page Returns: nothing Note: * The valid page numbers depend on the current display mode. } FUNCTION GetPointerPage : word; { Returns the current display page for the mouse pointer. } PROCEDURE DisableMouseDrvr(VAR Handler : pointer; VAR Err : boolean); { Disables the mouse driver and returns the address of the previous Int 33H handler. Call: nothing Returns: Handler = pointer to previous Int 33H handler Err = false if successful, true otherwise Notes: * When this procedure is called, the mouse driver releases any interrupt vectors it hase captured OTHER than Int 33H (which may be Int 10H, Int 71H, and/or Int 74H). The application program can COMPLETE the process of logically removing the mouse driver by restoring the original contents of the Int 33H vector with SetIntVec using the pointer returned by the procedure. * Also see EnableMouseDrvr. } PROCEDURE EnableMouseDrvr; { Enables the mouse driver and the servicing fo mouse interrupts. Call: nothing Returns: nothing Note: * Also see DisableMouseDrvr } PROCEDURE ResetMouseDrvr(VAR Buttons : word; VAR Err : boolean); { Resets the mouse driver and returns driver status. If the mouse pointer was previously visible, is is removed trom the screen, and any presoiusly installed user event handlers for mouse events are disabled. Call: nothing Returns: Buttons = number of mouse buttons Err = false if mouse support is available, true otherwise Note: * This procedure differ from InitMouse in that there is no initialization of the mouse hardware. } PROCEDURE SetMouseLang(LangNumber : word); { Selects the language that will be used by the mouse driver for prompts and error messages. Call: LangNumber = language number 0 = English 1 = French 2 = Dutch 3 = German 4 = Swedish 5 = Finnish 6 = Spanish 7 = Portuguese 8 = Italian Returns: nothing Note: * This procedure is only functional in international versions of the Microsoft Mouse drive. } FUNCTION GetMouseLang : word; { Returns the number of the language that is used by the mouse driver for prompts and error messages. Call: nothing Returns: language number (see above) Note: * This procedure is only functional in international versions of the Microsoft Mouse drive. } PROCEDURE GetMouseInfo(VAR MajVer, MinVer, MouseType, IRQ : word); { Returns the mouse driver version number, mouse type, and the IRQ number of the interrupt used by the mouse adapter. Call: nothing Returns: MajVer = major version number (6 for version 6.10, etc.) MinVer = minor version number (10 for version 6.10, etc.) MouseType = mouse type 1 = bus mouse 2 = serial mouse 3 = InPort mouse 4 = PS/2 mouse 5 = HP mouse IRQ = IRQ number 0 = PS/2 2, 3, 4, 5, or 7 = IRQ number } IMPLEMENTATION CONST MouseInt = $33; VAR Reg : Registers; PROCEDURE InitMouse(VAR Buttons : word; VAR Err : boolean); { Iniialize the mouse driver, if present, and return the number of buttons. } BEGIN Reg.AX := 0; intr(MouseInt, Reg); Buttons := Reg.BX; IF (Reg.AX = 0) THEN Err := true ELSE Err := false; END; PROCEDURE ShowPointer; BEGIN Reg.AX := 1; intr(MouseInt, Reg); END; PROCEDURE HidePointer; BEGIN Reg.AX := 2; intr(MouseInt, Reg); END; FUNCTION ButtonPressed(Mask : word) : boolean; BEGIN Reg.AX := 3; intr(MouseInt, Reg); IF (Reg.BX > 0) THEN ButtonPressed := true ELSE ButtonPressed := false; END; PROCEDURE GetMousePosition(VAR Buttons, Horiz, Vert : word); BEGIN Reg.AX := 3; intr(MouseInt, Reg); Buttons := Reg.BX; Horiz := Reg.CX; Vert := Reg.DX; END; FUNCTION MouseIn(x1,y1,x2,y2: word):boolean; VAR b,x,y: word; BEGIN GetMousePosition(b,x,y); MouseIn:=(x>=x1) AND (x<=x2) AND (y>=y1) AND (y<=y2) END; PROCEDURE SetPointerPosition(Horiz, Vert : word); BEGIN Reg.AX := 4; Reg.CX := Horiz; Reg.DX := Vert; intr(MouseInt, Reg); END; PROCEDURE GetPressInfo(Button : word; VAR Stat, Count, Horiz, Vert : word); BEGIN Reg.AX := 5; Reg.BX := Button; intr(MouseInt, Reg); Stat := Reg.AX; Count := Reg.BX; Horiz := Reg.CX; Vert := Reg.DX; END; PROCEDURE GetReleaseInfo(Button : word; VAR Stat, Count, Horiz, Vert : word); BEGIN Reg.AX := 6; Reg.BX := Button; intr(MouseInt, Reg); Stat := Reg.AX; Count := Reg.BX; Horiz := Reg.CX; Vert := Reg.DX; END; PROCEDURE SetLimits(HorMin, HorMax, VerMin, VerMax : word); BEGIN IF (HorMin > 0) AND (HorMax > 0) THEN BEGIN Reg.AX := 7; Reg.CX := HorMin; Reg.DX := HorMax; intr(MouseInt, Reg); END; IF (VerMin > 0) AND (VerMax > 0) THEN BEGIN Reg.AX := 8; Reg.CX := VerMin; Reg.DX := VerMax; intr(MouseInt, Reg); END; END; PROCEDURE SetPointerShape(Horiz, Vert : word; Buffer : pointer); BEGIN Reg.AX := 9; Reg.BX := Horiz; Reg.CX := Vert; Reg.ES := Seg(Buffer); Reg.DX := Ofs(Buffer); intr(MouseInt, Reg); END; PROCEDURE SetTextPointer(PtrTyp, AND_Str, XOR_End : word); BEGIN Reg.AX := 10; Reg.BX := PtrTyp; Reg.CX := AND_Str; Reg.DX := XOR_End; intr(MouseInt, Reg); END; PROCEDURE GetMotionCount(VAR Horiz, Vert : word); BEGIN Reg.AX := 11; intr(MouseInt, Reg); Horiz := Reg.CX; Vert := Reg.DX; END; PROCEDURE SetEventHandler(EventMask : word; Handler : pointer); BEGIN Reg.AX := 12; Reg.CX := EventMask; Reg.ES := seg(Handler); Reg.DX := ofs(Handler); intr(MouseInt, Reg); END; PROCEDURE SetLightPen(On_Off : word); BEGIN IF (On_Off = 0) THEN Reg.AX := 14 ELSE Reg.AX := 13; intr(MouseInt, Reg); END; PROCEDURE SetPointerExcl(HorMin, VerMin, HorMax, VerMax : word); BEGIN Reg.AX := 16; Reg.CX := HorMin; Reg.SI := HorMax; Reg.DX := VerMin; Reg.DI := VerMax; intr(MouseInt, Reg); END; PROCEDURE SwapEventHandlers(VAR Mask : word; VAR Buffer : pointer); BEGIN Reg.AX := 20; Reg.CX := Mask; Reg.ES := Seg(Buffer); Reg.DX := Ofs(Buffer); intr(MouseInt, Reg); Mask := Reg.CX; Buffer := Ptr(Reg.ES, Reg.DX); END; FUNCTION GetSaveStateSize : word; BEGIN Reg.AX := 21; intr(MouseInt, Reg); GetSaveStateSize := Reg.BX; END; PROCEDURE SaveDrvrState(Buffer : pointer); BEGIN Reg.AX := 22; Reg.ES := Seg(Buffer); Reg.DX := Ofs(Buffer); intr(MouseInt, Reg); END; PROCEDURE RestoreDrvrState(Buffer : pointer); BEGIN Reg.AX := 23; Reg.ES := Seg(Buffer); Reg.DX := Ofs(Buffer); intr(MouseInt, Reg); END; PROCEDURE SetAltEventHandler(Mask : word; Handler : pointer; VAR Err: boolean); BEGIN Reg.AX := 24; Reg.CX := Mask; Reg.ES := Seg(Handler); Reg.DX := Ofs(Handler); intr(MouseInt, Reg); IF (Reg.AX = 24) THEN Err := false ELSE Err := true; END; PROCEDURE GetAltEventAdrs(VAR Mask : word; VAR Handler : pointer; VAR Err : boolean); BEGIN Reg.AX := 25; Reg.CX := Mask; intr(MouseInt, Reg); IF (Reg.CX > 0) THEN BEGIN Mask := Reg.CX; Handler := Ptr(Reg.ES, Reg.DX); Err := false; END ELSE Err := true; END; PROCEDURE SetMouseSense(Horiz, Vert, Double : word); BEGIN Reg.AX := 26; Reg.BX := Horiz; Reg.CX := Vert; Reg.DX := Double; intr(MouseInt, Reg); END; PROCEDURE GetMouseSense(VAR Horiz, Vert, Double : word); BEGIN Reg.AX := 27; intr(MouseInt, Reg); Horiz := Reg.BX; Vert := Reg.CX; Double := Reg.DX; END; PROCEDURE SetMouseIntr(Flags : word); BEGIN Reg.AX := 28; Reg.BX := Flags; intr(MouseInt, Reg); END; PROCEDURE SetPointerPage(Page : word); BEGIN Reg.AX := 29; Reg.BX := Page; intr(MouseInt, Reg); END; FUNCTION GetPointerPage : word; BEGIN Reg.AX := 30; intr(MouseInt, Reg); GetPointerPage := Reg.BX; END; PROCEDURE DisableMouseDrvr(VAR Handler : pointer; VAR Err : boolean); BEGIN Reg.AX := 31; intr(MouseInt, Reg); IF (Reg.AX = 31) THEN BEGIN Handler := ptr(Reg.ES, Reg.DX); Err := false; END ELSE Err := true; END; PROCEDURE EnableMouseDrvr; BEGIN Reg.AX := 32; intr(MouseInt, Reg); END; PROCEDURE ResetMouseDrvr(VAR Buttons : word; VAR Err : boolean); BEGIN Reg.AX := 33; intr(MouseInt, Reg); IF (Reg.AX = $FFFF) THEN BEGIN Buttons := Reg.BX; Err := false; END ELSE Err := true; END; PROCEDURE SetMouseLang(LangNumber : word); BEGIN Reg.AX := 34; Reg.BX := LangNumber; intr(MouseInt, Reg); END; FUNCTION GetMouseLang : word; BEGIN Reg.AX := 35; intr(MouseInt, Reg); GetMouseLang := Reg.BX; END; PROCEDURE GetMouseInfo(VAR MajVer, MinVer, MouseType, IRQ : word); BEGIN Reg.AX := 36; intr(MouseInt, Reg); MajVer := Reg.BH; MinVer := Reg.BL; MouseType := Reg.CH; IRQ := Reg.CL; END; END. -- Ticking away, the moments that make up a dull day. | William C. Thompson You fritter and waste the hours in an offhand way. | Michelson 620D (wct) Kicking around on a piece of ground in your hometown,| a.k.a. Master of Time, waiting for someone or something to show you the way.| Space, and Dimension