[Back to MOUSE SWAG index]  [Back to Main SWAG index]  [Original]

UNIT Mouse;
{*****************************************************************************}
                               INTERFACE
{*****************************************************************************}
USES DOS;

TYPE mouse_cursor_mask = RECORD
                         screen_mask : ARRAY[0..7] OF BYTE;
                         cursor_mask : ARRAY[8..15] OF BYTE;
                         END;

CONST on = TRUE;
CONST off = FALSE;
CONST left = $00;
CONST right = $01;

CONST change_in_cursor_position = $0001;         {call masks for user defined}
CONST left_button_pressed = $0002;               {input mask and swap vectors}
CONST left_button_released = $0004;
CONST right_button_pressed = $0008;
CONST right_button_released = $0010;

CONST alternate_key_pressed = $0001;   {call masks for alternate user handlers}
CONST control_key_pressed = $0002;
CONST shift_button_pressed = $0004;
CONST right_button_up = $0008;
CONST right_button_down = $0010;
CONST left_button_up = $0020;
CONST left_button_down = $0040;
CONST cursor_moved = $0080;

VAR mouse_driver_disabled : BOOLEAN;
VAR number_of_presses, number_of_releases : INTEGER;
VAR number_buttons, x, y : INTEGER;
VAR button_status, horizontal_counts, vertical_counts : INTEGER;
VAR left_mouse_button_pressed, right_mouse_button_pressed,
    left_mouse_button_released, right_mouse_button_released : BOOLEAN;
VAR register : REGISTERS;

PROCEDURE check_button_status;
PROCEDURE disable_mouse_driver (VAR int33h_vector_address : POINTER);
PROCEDURE enable_mouse_driver; INLINE($B8/$20/$00/$CD/$33);
FUNCTION  get_alternate_user_interrupt_vector (call_mask : WORD) : POINTER;
PROCEDURE get_left_button_press_information;
PROCEDURE get_left_button_release_information;
PROCEDURE get_mouse_position;
PROCEDURE get_mouse_sensitivity (VAR horizontal_coordinates_per_pixel,
                                     vertical_coordinates_per_pixel,
                                     double_speed_threshold : WORD);
PROCEDURE get_right_button_press_information;
PROCEDURE get_right_button_release_information;
PROCEDURE light_pen_emulation; INLINE($B8/$0D/$00/$CD/$33);
FUNCTION  mouse_button_pressed : BOOLEAN;
PROCEDURE mouse_cursor_off; INLINE($B8/$02/$00/$CD/$33);
PROCEDURE mouse_cursor_off_area (x1,y1,x2,y2 : INTEGER);
PROCEDURE mouse_cursor_on; INLINE($B8/$01/$00/$CD/$33);
FUNCTION  mouse_exists : BOOLEAN;
FUNCTION  mouse_state_buffer_size : INTEGER;
FUNCTION  mouse_video_page : WORD;
FUNCTION  number_of_buttons : INTEGER;
PROCEDURE relative_number_of_screen_positions_moved (VAR x, y : INTEGER);
          {reported in units of 0.02 inches - approximately 0.5 millimeters}
PROCEDURE reset_mouse_software; INLINE($B8/$21/$00/$CD/$33);
PROCEDURE restore_mouse_driver_state (mouse_state_buffer_segment,
                                      mouse_state_buffer_offset : WORD);
          {use when returning from another program to your program}
PROCEDURE save_mouse_driver_state (mouse_state_buffer_segment,
                                   mouse_state_buffer_offset : WORD);
          {use mouse_state_buffer_size to set up buffer first;
           use when EXEC another program from your program}
PROCEDURE set_alternate_mouse_user_handler (call_mask,
                                            function_offset : INTEGER);
PROCEDURE set_double_speed_threshold (threshold_speed : INTEGER);
PROCEDURE set_graphics_mouse_cursor (hot_spot_x, hot_spot_y : INTEGER;
                                   screen_and_cursor_mask : mouse_cursor_mask);
PROCEDURE set_mouse_physical_movement_ratio (x8_positions_to_move,
                                             y8_positions_to_move : INTEGER);
          {each position corresponds to 1/200th of an inch}
PROCEDURE set_mouse_position (x,y : INTEGER);
PROCEDURE set_mouse_sensitivity (horizontal_coordinates_per_pixel,
                                 vertical_coordinates_per_pixel,
                                 double_speed_threshold : WORD);
PROCEDURE set_mouse_video_page (page_number : WORD);
PROCEDURE set_mouse_x_bounds (minimum_x, maximum_x : WORD);
PROCEDURE set_mouse_y_bounds (minimum_y, maximum_y : WORD);
PROCEDURE set_text_mouse_attribute_cursor (screen_cursor_mask_offset : WORD);
PROCEDURE set_text_mouse_hardware_cursor (top_scan_line,
                                          bottom_scan_line : INTEGER);
PROCEDURE stop_light_pen_emulation; INLINE($B8/$0E/$00/$CD/$33);
PROCEDURE swap_mouse_interrupt_vector (VAR call_mask, mouse_vector_segment,
                                           mouse_vector_offset : WORD);
{*****************************************************************************}
                             IMPLEMENTATION
{*****************************************************************************}
PROCEDURE check_button_status;
   VAR check_left, check_right : WORD;
   BEGIN
      IF button_status AND $0001 = $0001 THEN
         left_mouse_button_pressed := TRUE ELSE
         left_mouse_button_pressed := FALSE;

      IF button_status AND $0002 = $0002 THEN
         right_mouse_button_pressed := TRUE ELSE
         right_mouse_button_pressed := FALSE;
   END;
{*****************************************************************************}
PROCEDURE disable_mouse_driver (VAR int33h_vector_address : POINTER);
   BEGIN
      register.AX := $001F;
      INTR($33,register);
      IF register.AX = $001F THEN
         BEGIN
            mouse_driver_disabled := TRUE;
            int33h_vector_address := PTR(register.ES,register.BX);
         END ELSE mouse_driver_disabled := FALSE;
   END;
{*****************************************************************************}
FUNCTION  get_alternate_user_interrupt_vector (call_mask : WORD) : POINTER;
   BEGIN
      register.AX := $0019;
      register.CX := call_mask;
      INTR($33,register);
      get_alternate_user_interrupt_vector := PTR(register.BX,register.DX);
   END;
{*****************************************************************************}
PROCEDURE get_left_button_press_information;
   BEGIN
      register.BX := $0000;
      register.AX := $0005;
      INTR($33,register);
      number_of_presses := register.BX;
      x := register.CX;
      y := register.DX;
      button_status := register.AX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE get_left_button_release_information;
   BEGIN
      register.BX := $0000;
      register.AX := $0006;
      INTR($33,register);
      number_of_releases := register.BX;
      x := register.CX;
      y := register.DX;
      button_status := register.AX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE get_mouse_position;
   BEGIN
      register.AX := $0003;
      INTR($33,register);
      x := register.CX;
      y := register.DX;
      button_status := register.BX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE get_mouse_sensitivity (VAR horizontal_coordinates_per_pixel,
                                     vertical_coordinates_per_pixel,
                                     double_speed_threshold : WORD);
   BEGIN
      register.AX := $001B;
      register.BX := horizontal_coordinates_per_pixel;
      register.CX := vertical_coordinates_per_pixel;
      register.DX := double_speed_threshold;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE get_right_button_press_information;
   BEGIN
      register.BX := $0001;
      register.AX := $0005;
      INTR($33,register);
      number_of_presses := register.BX;
      x := register.CX;
      y := register.DX;
      button_status := register.AX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE get_right_button_release_information;
   BEGIN
      register.BX := $0001;
      register.AX := $0006;
      INTR($33,register);
      number_of_releases := register.BX;
      x := register.CX;
      y := register.DX;
      button_status := register.AX;
      check_button_status;
   END;
{*****************************************************************************}
FUNCTION mouse_button_pressed : BOOLEAN;
   BEGIN
      register.AX := $0003;
      INTR($33,register);
      button_status := register.BX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE mouse_cursor_off_area (x1,y1,x2,y2 : INTEGER);
   BEGIN
      register.AX := $0010;
      register.CX := x1;
      register.DX := y1;
      register.SI := x2;
      register.DI := y2;
      INTR($33,register);
      mouse_cursor_on;   {may need to remove this statement}
   END;
{*****************************************************************************}
FUNCTION  mouse_exists : BOOLEAN;
   BEGIN
      register.AX := $0021;
      INTR($33,register);
      IF (register.AX = $FFFF) AND (register.BX = $02) THEN
         mouse_exists := TRUE ELSE
         mouse_exists := FALSE;
   END;
{*****************************************************************************}
FUNCTION  mouse_state_buffer_size : INTEGER;
   BEGIN
      register.AX := $15;
      INTR($33,register);
      mouse_state_buffer_size := register.BX;
   END;
{*****************************************************************************}
FUNCTION mouse_video_page : WORD;
   BEGIN
      INLINE($B8/$1E/$00/$CD/$33);
      mouse_video_page := register.BX;
   END;
{*****************************************************************************}
FUNCTION number_of_buttons : INTEGER;
   BEGIN
      register.AX := $0000;
      INTR($33,register);
      number_of_buttons := register.BX;
   END;
{*****************************************************************************}
PROCEDURE relative_number_of_screen_positions_moved (VAR x, y : INTEGER);
   BEGIN
      register.AX := $000B;
      INTR($33,register);
      register.CX := x;
      register.DX := y;
   END;
{*****************************************************************************}
PROCEDURE restore_mouse_driver_state (mouse_state_buffer_segment,
                                      mouse_state_buffer_offset : WORD);
   BEGIN
      register.AX := $17;
      register.ES := mouse_state_buffer_segment;
      register.DX := mouse_state_buffer_offset;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE save_mouse_driver_state (mouse_state_buffer_segment,
                                   mouse_state_buffer_offset : WORD);
   BEGIN
      register.AX := $16;
      register.ES := mouse_state_buffer_segment;
      register.DX := mouse_state_buffer_offset;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_alternate_mouse_user_handler (call_mask,
                                            function_offset : INTEGER);
   BEGIN
      register.AX := $0018;
      register.CX := call_mask;
      register.DX := function_offset;
      INTR($33,register);
      x := register.CX;
      y := register.DX;
      horizontal_counts := register.DI;
      vertical_counts := register.SI;
      button_status := register.BX;
      check_button_status;
   END;
{*****************************************************************************}
PROCEDURE set_mouse_video_page (page_number : WORD);
   BEGIN
      register.AX := $001D;
      register.BX := page_number;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_double_speed_threshold (threshold_speed : INTEGER);
   BEGIN
      register.AX := $0013;
      register.DX := threshold_speed;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_graphics_mouse_cursor (hot_spot_x, hot_spot_y : INTEGER;
                                   screen_and_cursor_mask : mouse_cursor_mask);
   BEGIN
      register.AX := $0009;
      register.BX := hot_spot_x;
      register.CX := hot_spot_y;
      register.ES := SEG(screen_and_cursor_mask);
      register.DX := OFS(screen_and_cursor_mask);
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_mouse_physical_movement_ratio (x8_positions_to_move,
                                             y8_positions_to_move : INTEGER);
   BEGIN
      register.AX := $000F;
      register.CX := x8_positions_to_move;
      register.DX := y8_positions_to_move;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_mouse_position (x,y : INTEGER);
   BEGIN
      register.AX := $0004;
      register.CX := x;
      register.DX := y;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_mouse_sensitivity (horizontal_coordinates_per_pixel,
                                 vertical_coordinates_per_pixel,
                                 double_speed_threshold : WORD);
   BEGIN
      register.AX := $001A;
      register.BX := horizontal_coordinates_per_pixel;
      register.CX := vertical_coordinates_per_pixel;
      register.DX := double_speed_threshold;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_mouse_x_bounds (minimum_x, maximum_x : WORD);
   BEGIN
      register.AX := $0008;
      register.CX := minimum_x;
      register.DX := maximum_x;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_mouse_y_bounds (minimum_y, maximum_y : WORD);
   BEGIN
      register.AX := $0007;
      register.CX := minimum_y;
      register.DX := maximum_y;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_text_mouse_attribute_cursor (screen_cursor_mask_offset : WORD);
   BEGIN
      register.AX := $000A;
      register.BX := $0000;
      register.CX := screen_cursor_mask_offset;
      register.DX := screen_cursor_mask_offset + 8;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_text_mouse_hardware_cursor (top_scan_line,
                                          bottom_scan_line : INTEGER);
   BEGIN
      register.AX := $000A;
      register.BX := $0001;
      register.CX := top_scan_line;
      register.DX := bottom_scan_line;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE set_user_defined_input_mask (call_mask, function_offset : INTEGER);
   BEGIN
      register.AX := $000C;
      register.CX := call_mask;
      register.DX := function_offset;
      INTR($33,register);
   END;
{*****************************************************************************}
PROCEDURE swap_mouse_interrupt_vector (VAR call_mask, mouse_vector_segment,
                                           mouse_vector_offset : WORD);
   VAR register_DS : INTEGER;
   BEGIN
      register_DS := register.DS;  {save the data segment}
      register.AX := $0014;
      register.CX := call_mask;
      register.ES := mouse_vector_offset;
      register.DX := mouse_vector_offset;
      INTR($33,register);
      call_mask := register.CX;
      mouse_vector_segment := register.ES;
      mouse_vector_offset := register.DX;
      register.DS := register_DS;   {resets the data segment}
      button_status := register.BX;
      check_button_status;
      horizontal_counts := register.DI;
      vertical_counts := register.SI;
      x := register.CX;
      y := register.DX;
   END;
{*****************************************************************************}
BEGIN
   x := 0;
   y := 0;
   number_buttons := number_of_buttons;
   number_of_presses := 0;
   number_of_releases := 0;
   left_mouse_button_released := FALSE;
   right_mouse_button_released := FALSE;
   left_mouse_button_released := FALSE;
   right_mouse_button_released := FALSE;
END.

[Back to MOUSE SWAG index]  [Back to Main SWAG index]  [Original]