#include /*-----------------------------------------------------------------------* | mouse_class: a text-oriented mouse interface | *-----------------------------------------------------------------------*/ #include #include "mouse.h" /*-----------------------------------------------------------------------* | Just including mouse.h and linking with mouse.cpp, causes a | | mouse_class object called "mouse", to be created automatically. | | | | You must use this mouse object in your programs, | | instead of creating your own mouse with a different name. | | | | Or else my mouse will bite yer arse. | *-----------------------------------------------------------------------*/ mouse_class mouse; mouse_class:: mouse_class() { set_double_click_period( DOUBLE_CLICK_PERIOD ); _last_left_click = clock() - _double_click_period; _last_right_click = _last_left_click; reset_driver(); } mouse_class::~mouse_class() { } bool mouse_class:: will_work() { return _will_work; } void mouse_class:: new_video_mode() { // set values of _mouse_pixels_per_col, _mouse_pixels_per_row // and _mouse_pixels_per_x switch( ScreenMode() ) { case 0: case 1: case 4: case 5: case 13: case 19: _mouse_pixels_per_col = 16; _mouse_pixels_per_row = 8; _mouse_pixels_per_x = 2; break; case 15: case 16: _mouse_pixels_per_col = 8; _mouse_pixels_per_row = 14; _mouse_pixels_per_x = 1; break; case 17: case 18: _mouse_pixels_per_col = 8; _mouse_pixels_per_row = 16; _mouse_pixels_per_x = 1; break; default: _mouse_pixels_per_col = 8; _mouse_pixels_per_row = 8; _mouse_pixels_per_x = 1; } // stop the cursor from disappearing entirely // when at the bottom or right of the screen set_x_limits( 0, ScreenCols() - 0.6 ); set_y_limits( 0, ScreenRows() - 0.6 ); } void mouse_class:: poll() { if( !_will_work ) return; union REGS registers; int current_event = 0; // call mouse driver sub-function 3 (poll mouse) registers.w.ax = 0x0003; int86( 0x33, ®isters, ®isters ); current_event = registers.w.bx; /*-----------------------------------------------------------------------* | this if() block sets the value of _left_double_click | *-----------------------------------------------------------------------*/ // see if left button is down if( current_event & mouse_left_click ) { // if it is, check if it's been released since last click if( !( _last_event & mouse_left_click ) ) { // if it has, see if the gap between clicks is short enough // to call it a double-click if( ( clock() - _last_left_click ) < _double_click_period ) current_event |= mouse_left_double_click; } // make a note of the time of this click (for next time) _last_left_click = clock(); } /*-----------------------------------------------------------------------* | this if() block sets the value of _right_double_click | *-----------------------------------------------------------------------*/ // see if right button is down if( current_event & mouse_right_click ) { // if it is, check if it's been released since last click if( !( _last_event & mouse_right_click ) ) { // if it has, see if the gap between clicks is short enough // to call it a double-click if( ( clock() - _last_right_click ) < _double_click_period ) current_event |= mouse_right_double_click; } // make a note of the time of this click (for next time) _last_right_click = clock(); } /*-----------------------------------------------------------------------* | this bit gets the cursor position and checks for movement | *-----------------------------------------------------------------------*/ // get text row and col positions _cursor_pos.x = registers.w.cx / _mouse_pixels_per_col; _cursor_pos.y = registers.w.dx / _mouse_pixels_per_row; // save old pixel x and y positions _old_x_pixel = _x_pixel; _old_y_pixel = _y_pixel; // get new pixel x and y positions _x_pixel = registers.w.cx / _mouse_pixels_per_x; _y_pixel = registers.w.dx; // check for movement if( _x_pixel != _old_x_pixel || _y_pixel != _old_y_pixel ) current_event |= mouse_movement; _last_event = current_event; } int mouse_class:: event() { return _last_event; } int mouse_class:: clicked() { return _last_event & ( mouse_left_click | mouse_right_click ); } bool mouse_class:: left_click() { return _last_event & mouse_left_click; } bool mouse_class:: left_double_click() { return _last_event & mouse_left_double_click; } bool mouse_class:: right_click() { return _last_event & mouse_right_click; } bool mouse_class:: right_double_click() { return _last_event & mouse_right_double_click; } bool mouse_class:: has_moved() { return _last_event & mouse_movement; } int mouse_class:: x() { return _cursor_pos.x; } int mouse_class:: y() { return _cursor_pos.y; } bool mouse_class:: is_over( rectangle & area ) { return area.contains( _cursor_pos.x, _cursor_pos.y ); } int mouse_class:: x_pixel() { return _x_pixel; } int mouse_class:: y_pixel() { return _y_pixel; } bool mouse_class:: is_over_pixel( rectangle& area ) { return area.contains( _x_pixel, _y_pixel ); } void mouse_class:: show_cursor( int number_of_times ) { if( !_will_work ) return; int i = 0; while( _visibility < 0 && i < number_of_times ) { union REGS registers; registers.w.ax = 0x0001; int86( 0x33, ®isters, ®isters ); _visibility++; i++; } } void mouse_class:: hide_cursor( int number_of_times ) { if( !_will_work ) return; int i = 0; while( i < number_of_times ) { union REGS registers; registers.w.ax = 0x0002; int86( 0x33, ®isters, ®isters ); _visibility--; i++; } } void mouse_class:: place_cursor( float col, float row ) { if( !_will_work ) return; union REGS registers; registers.w.ax = 0x0004; registers.w.cx = (unsigned)( col * _mouse_pixels_per_col ); registers.w.dx = (unsigned)( row * _mouse_pixels_per_row ); int86( 0x33, ®isters, ®isters ); } void mouse_class:: set_double_click_period( double seconds ) { _double_click_period = (clock_t)( seconds * CLOCKS_PER_SEC ); } void mouse_class:: set_sensitivity( unsigned x_sense, unsigned y_sense ) { if( !_will_work ) return; union REGS registers; if( x_sense > 0 && y_sense > 0 ) { registers.w.ax = 0x000F; registers.w.cx = x_sense; registers.w.dx = y_sense; int86( 0x33, ®isters, ®isters ); } } void mouse_class:: set_x_limits( float leftmost_x, float rightmost_x ) { if( !_will_work ) return; union REGS registers; registers.w.ax = 0x0007; registers.w.cx = (unsigned)( leftmost_x * _mouse_pixels_per_col ); registers.w.dx = (unsigned)( rightmost_x * _mouse_pixels_per_col ); int86( 0x33, ®isters, ®isters ); } void mouse_class:: set_y_limits( float top_y, float bottom_y ) { if( !_will_work ) return; union REGS registers; registers.w.ax = 0x0008; registers.w.cx = (unsigned)( top_y * _mouse_pixels_per_row ); registers.w.dx = (unsigned)( bottom_y * _mouse_pixels_per_row ); int86( 0x33, ®isters, ®isters ); } bool mouse_class:: reset_driver() { union REGS registers; // call mouse driver sub-function 0 (reset driver) registers.w.ax = 0x0000; int86( 0x33, ®isters, ®isters ); // detect driver if( registers.w.ax == 0xFFFF ) _will_work = true; else _will_work = false; // if driver present, prepare initial values if( _will_work ) { // set _mouse_pixels_per_row, _mouse_pixels_per_col // and mouse_pixels_per_x for the current video mode new_video_mode(); // put accurate info in member variables poll(); // make sure _visibility counter is accurate _visibility = -100; show_cursor( 100 ); hide_cursor(); } return _will_work; } int mouse_class:: visibility() { return _visibility; } void mouse_class:: save_visibility() { _saved_visibility = _visibility; } void mouse_class:: set_visibility( int new_setting ) { if( new_setting > 0 ) return; if( new_setting > _visibility ) show_cursor( new_setting - _visibility ); else if( new_setting < _visibility ) hide_cursor( _visibility - new_setting ); } void mouse_class:: restore_visibility() { set_visibility( _saved_visibility ); }