/* mouse.c - The following program demonstrates how to use the mouse interrupt (0x33) with DOS/4GW. Compile and link: wcl386 -l=dos4g mouse */ #include #include #include /* Data touched at mouse callback time -- they are in a structure to simplify calculating the size of the region to lock. */ struct callback_data { int right_button; int mouse_event; unsigned short mouse_code; unsigned short mouse_bx; unsigned short mouse_cx; unsigned short mouse_dx; signed short mouse_si; signed short mouse_di; } cbd = { 0 }; /* Set up data buffer for mouse cursor bitmap */ unsigned short cursor[] = { /* 16 words of screen mask */ 0x3fff, /*0011111111111111*/ 0x1fff, /*0001111111111111*/ 0x0fff, /*0000111111111111*/ 0x07ff, /*0000011111111111*/ 0x03ff, /*0000001111111111*/ 0x01ff, /*0000000111111111*/ 0x00ff, /*0000000011111111*/ 0x007f, /*0000000001111111*/ 0x01ff, /*0000000111111111*/ 0x10ff, /*0001000011111111*/ 0xb0ff, /*1011000011111111*/ 0xf87f, /*1111100001111111*/ 0xf87f, /*1111100001111111*/ 0xfc3f, /*1111110000111111*/ 0xfc3f, /*1111110000111111*/ 0xfe1f, /*1111111000011111*/ /* 16 words of cursor mask */ 0x0000, /*0000000000000000*/ 0x4000, /*0100000000000000*/ 0x6000, /*0110000000000000*/ 0x7000, /*0111000000000000*/ 0x7800, /*0111100000000000*/ 0x7c00, /*0111110000000000*/ 0x7e00, /*0111111000000000*/ 0x7f00, /*0111111100000000*/ 0x7c00, /*0111110000000000*/ 0x4600, /*0100011000000000*/ 0x0600, /*0000011000000000*/ 0x0300, /*0000001100000000*/ 0x0300, /*0000001100000000*/ 0x0180, /*0000000110000000*/ 0x0180, /*0000000110000000*/ 0x00c0, /*0000000011000000*/ }; int lock_region( void *address, unsigned length ) { union REGS regs; unsigned linear; /* Thanks to DOS/4GW's zero-based flat memory model, converting a pointer of any type to a linear address is trivial. */ linear = (unsigned)address; /* DPMI Lock Linear Region */ regs.w.ax = 0x600; /* Linear address in BX:CX */ regs.w.bx = (unsigned short)(linear >> 16); regs.w.cx = (unsigned short)(linear & 0xFFFF); /* Length in SI:DI */ regs.w.si = (unsigned short)(length >> 16); regs.w.di = (unsigned short)(length & 0xFFFF); int386( 0x31, ®s, ®s ); /* Return 0 if lock failed */ return( !regs.w.cflag ); } #pragma off( check_stack ) void _loadds far click_handler( int max, int mbx, int mcx, int mdx, int msi, int mdi ) { #pragma aux click_handler parm [EAX] [EBX] [ECX] \ [EDX] [ESI] [EDI] cbd.mouse_event = 1; cbd.mouse_code = (unsigned short)max; cbd.mouse_bx = (unsigned short)mbx; cbd.mouse_cx = (unsigned short)mcx; cbd.mouse_dx = (unsigned short)mdx; cbd.mouse_si = (signed short)msi; cbd.mouse_di = (signed short)mdi; if( cbd.mouse_code & 8 ) cbd.right_button = 1; } /* Dummy function so we can calculate size of code to lock (cbc_end - click_handler). */ void cbc_end( void ) { } #pragma on( check_stack ) void main (void) { struct SREGS sregs; union REGS inregs, outregs; int installed = 0; unsigned char orig_mode = 0; unsigned short far *ptr; void (far *function_ptr)(); segread( &sregs ); /* get original video mode */ inregs.w.ax = 0x0f00; int386( 0x10, &inregs, &outregs ); orig_mode = outregs.h.al; /* goto graphics mode */ inregs.h.ah = 0x00; inregs.h.al = 0x6; int386( 0x10, &inregs, &outregs ); printf( "Previous Mode = %u\n", orig_mode ); printf( "Current Mode = %u\n", inregs.h.al ); /* check for mouse driver */ inregs.w.ax = 0; int386( 0x33, &inregs, &outregs ); if( installed = (outregs.w.ax == 0xffff) ) printf( "Mouse installed...\n" ); else printf( "Mouse NOT installed...\n" ); if( installed ) { /* lock callback code and data (essential under VMM!) note that click_handler, although it does a far return and is installed using a full 48-bit pointer, is really linked into the flat model code segment -- so we can use a regular (near) pointer in the lock_region() call. */ if( (! lock_region( &cbd, sizeof( cbd ) )) || (! lock_region( (void near *)click_handler, (char *)cbc_end - (char near *)click_handler )) ) { printf( "locks failed\n" ); } else { /* show mouse cursor */ inregs.w.ax = 0x1; int386( 0x33, &inregs, &outregs ); /* set mouse cursor form */ inregs.w.ax = 0x9; inregs.w.bx = 0x0; inregs.w.cx = 0x0; ptr = cursor; inregs.x.edx = FP_OFF( ptr ); sregs.es = FP_SEG( ptr ); int386x( 0x33, &inregs, &outregs, &sregs ); /* install click watcher */ inregs.w.ax = 0xC; inregs.w.cx = 0x0002 + 0x0008; function_ptr = ( void (far *)( void ) )click_handler; inregs.x.edx = FP_OFF( function_ptr ); sregs.es = FP_SEG( function_ptr ); int386x( 0x33, &inregs, &outregs, &sregs ); while( !cbd.right_button ) { if( cbd.mouse_event ) { printf( "Ev %04hxh BX %hu CX %hu DX %hu " "SI %hd DI %hd\n", cbd.mouse_code, cbd.mouse_bx, cbd.mouse_cx, cbd.mouse_dx, cbd.mouse_si, cbd.mouse_di ); cbd.mouse_event = 0; } } } } /* check installation again (to clear watcher) */ inregs.w.ax = 0; int386( 0x33, &inregs, &outregs ); if( outregs.w.ax == 0xffff ) printf( "DONE : Mouse still installed...\n" ); else printf( "DONE : Mouse NOT installed...\n" ); printf( "Press Enter key to return to original mode\n" ); getc( stdin ); inregs.h.ah = 0x00; inregs.h.al = orig_mode; int386( 0x10, &inregs, &outregs ); }