#include "windows.h" #include "insignia.h" #include "host_def.h" #include #include #include #include "conapi.h" #include "xt.h" #include CpuH #include "egacpu.h" #include "trace.h" #include "debug.h" #include "gvi.h" #include "error.h" #include "config.h" #include "bios.h" #include "mouse_io.h" #include "video.h" #include "nt_graph.h" #include "host_nls.h" #include "sas.h" #include "ica.h" #include "idetect.h" #include "host_rrr.h" #include "nt_mouse.h" #include "ntcheese.h" #include "nt_uis.h" #include "nt_reset.h" #include "nt_eoi.h" #include "nt_event.h" #include #include "nt_fulsc.h" #define TEXT_MODE 1 #define GRAPHICS_MODE 2 #define NOTHING 0xff #define NOT_INSTALLED 0 #define INSTALLED 1 #define get_pix_height() (get_pc_pix_height() * get_host_pix_height()) GLOBAL BOOL pointer_emulation_status = POINTER_EMULATION_OS; GLOBAL word VirtualX,VirtualY; GLOBAL BOOL bPointerOff=FALSE; GLOBAL MOUSE_STATUS os_pointer_data; IMPORT word DRAW_FS_POINTER_SEGMENT, DRAW_FS_POINTER_OFFSET; IMPORT word POINTER_OFF_SEGMENT, POINTER_OFF_OFFSET; IMPORT word POINTER_ON_SEGMENT, POINTER_ON_OFFSET; IMPORT word CP_X_S, CP_X_O, CP_Y_S, CP_Y_O; IMPORT sys_addr conditional_off_sysaddr; IMPORT word F9_SEGMENT,F9_OFFSET; IMPORT word savedtextoffset,savedtextsegment; #ifdef X86GFX IMPORT sys_addr mouseCFsysaddr; // sas address of internal cursor flag IMPORT word button_off,button_seg; IMPORT boolean mouse_io_interrupt_busy; #define cursor_in_black_hole(cpx, cpy) \ (cpx >= black_hole.top_left.x && \ cpx <= black_hole.bottom_right.x && \ cpy >= black_hole.top_left.y && \ cpy <= black_hole.bottom_right.y) #endif //X86GFX LOCAL BOOL mouse_state; LOCAL BOOL bFullscTextBkgrndSaved = FALSE; LOCAL BOOL bPointerInSamePlace = FALSE; LOCAL word text_ptr_bkgrnd=0; // safe place for screen background LOCAL sys_addr old_text_addr; RECT WarpBorderRect; // in screen coordinates RECT WarpClientRect; // in client coordinates LOCAL POINT pMiddle; // centre point of the current Console window LOCAL POINT pLast = {0,0}; LOCAL BOOL bAlertMessage=TRUE; LOCAL BOOL b256mode=FALSE; LOCAL int old_x=319; // previous pointer state (position) LOCAL int old_y=99; // in virtual coordinates. LOCAL short m2pX=8,m2pY=16; // Mickey to pixel ratios LOCAL BOOL bFunctionZeroReset = TRUE; LOCAL BOOL bFunctionFour = FALSE; LOCAL IS16 newF4x,newF4y; GLOBAL VOID host_os_mouse_pointer(MOUSE_CURSOR_STATUS *,MOUSE_CALL_MASK *, MOUSE_VECTOR *); FORWARD BOOL WarpSystemPointer(IS16 *,IS16 *); FORWARD void MovePointerToWindowCentre(void); FORWARD void host_mouse_install1(void); FORWARD void host_mouse_install2(void); FORWARD void mouse_restore_cursor(void); FORWARD void deinstall_host_mouse(void); FORWARD BOOL mouse_installed(void); FORWARD BOOL mouse_in_use(void); FORWARD void mouse_reset(void); FORWARD void mouse_set_position(USHORT,USHORT); FORWARD void mouse_cursor_display(void); FORWARD void mouse_cursor_undisplay(void); FORWARD void mouse_cursor_mode_change(void); FORWARD BOOL HasConsoleClientRectChanged(void); FORWARD void MouseDisplay(); FORWARD void CToS(RECT *); FORWARD void MouseDetachMenuItem(BOOL); FORWARD void MouseAttachMenuItem(HANDLE); FORWARD void MouseReattachMenuItem(HANDLE); FORWARD void ResetMouseOnBlock(void); FORWARD void ScaleToWindowedVirtualCoordinates(IS16 *,IS16 *,MOUSE_VECTOR *); FORWARD void host_m2p_ratio(word *,word *,word *,word *); FORWARD void host_x_range(word *,word *,word *,word *); FORWARD void host_y_range(word *,word *,word *,word *); FORWARD void EmulateCoordinates(half_word,IS16,IS16,IS16 *,IS16 *); FORWARD void AssembleCallMask(MOUSE_CALL_MASK *); FORWARD void FullscTextPtr(int, int); FORWARD void WindowedGraphicsScale(half_word,IS16,IS16,IS16 *,IS16 *); FORWARD void dummy(short *,short *,unsigned short *); FORWARD void LimitCoordinates(half_word,IS16 *,IS16 *); #ifdef X86GFX FORWARD void CleanUpMousePointer(); FORWARD void FullscreenWarpSystemPointer(POINT *); FORWARD void ScaleToFullscreenVirtualCoordinates(IS16 *,IS16 *,MOUSE_VECTOR *); #endif //X86GFX FORWARD void TextScale(IS16 *,IS16 *,IS16 *, IS16 *); void LazyMouseInterrupt(); VOID MouseEoiHook(int IrqLine, int CallCount); BOOLEAN bSuspendMouseInterrupts=FALSE; GLOBAL HOSTMOUSEFUNCS the_mouse_funcs = { mouse_restore_cursor, deinstall_host_mouse, mouse_installed, mouse_in_use, mouse_reset, mouse_set_position, dummy, mouse_cursor_display, mouse_cursor_undisplay, mouse_cursor_mode_change }; BOOL bMouseMenuItemAdded=FALSE; HMENU hM; // // look up table to convert the video mode number to a mode type indicator // LOCAL half_word TextOrGraphicsModeLUT[] = { TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, GRAPHICS_MODE, GRAPHICS_MODE,GRAPHICS_MODE,NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, GRAPHICS_MODE,GRAPHICS_MODE, GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE, GRAPHICS_MODE,NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, TEXT_MODE, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING, GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE }; LOCAL int VirtualScrCtrLUTx[] = { 319, // mode 0 319, // mode 1 319, // mode 2 319, // mode 3 319, // mode 4 319, // mode 5 319, // mode 6 319, // mode 7 319, // mode 8 319, // mode 9 319, // mode a 319, // mode b 319, // mode c 319, // mode d 319, // mode e 319, // mode f 319, // mode 10 319, // mode 11 319, // mode 12 159 // mode 13 }; LOCAL int VirtualScrCtrLUTy[] = { 99, // mode 0 99, // mode 1 99, // mode 2 99, // mode 3 99, // mode 4 99, // mode 5 99, // mode 6 99, // mode 7 99, // mode 8 99, // mode 9 99, // mode a 99, // mode b 99, // mode c 99, // mode d 99, // mode e 174, // mode f 174, // mode 10 239, // mode 11 239, // mode 12 99 // mode 13 }; // // A look up table to convert a console cell location to a virtual pixel // coordinate. // int ConsoleTextCellToVPCellLUT[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344, 352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456, 464, 472, 480, 488, 496, 504, 512, 520, 528, 536, 544, 552, 560, 568, 576, 584, 592, 600, 608, 616, 624, 632, 640, 648, 656, 664, 672, 680, 688, 696 }; // // This structure holds the information provided by int 33h functions 7 and 8. // If one of these functions have been called, then the appropriate flag in // the structure is set and the handler for this will ignore the default bounds // for the current video mode and will use the values in the structure instead. // The flags will clear if a mode change has been detected too. // struct { word xmin; word ymin; word xmax; word ymax; BOOL bF7; BOOL bF8; } confine = {0,0,639,199,FALSE,FALSE}; // // Mouse interrupt regulation mechanisms // BOOLEAN bMseEoiPending = FALSE; ULONG MseIntLazyCount = 0; // // // The code starts here // // GLOBAL void host_mouse_install1(void) { mouse_state = INSTALLED; RegisterEOIHook(9, MouseEoiHook); mouse_install1(); } GLOBAL void host_mouse_install2(void) { mouse_install2(); } GLOBAL void mouse_restore_cursor() { /* If mouse not in use exit */ if(!mouse_in_use()) return; } GLOBAL void deinstall_host_mouse() { mouse_state = NOT_INSTALLED; } GLOBAL BOOL mouse_installed() { return (mouse_state); } void dummy(short *pooh1,short *pooh2, unsigned short *pooh3) { } GLOBAL BOOL mouse_in_use() { return(mouse_state == INSTALLED && in_text_mode() == FALSE); } GLOBAL void mouse_reset() { #ifdef X86GFX half_word vm; word xx,yy; // // Set the internal cursor flag to "just off" // the real driver sets the internal cursor flag to -1 // so do I. // sas_store(mouseCFsysaddr,0xff); // cursor hidden // // Set the fast track position words in the 16 bit driver. // First igure out the video mode, and from this, the virtual // screen centre. // sas_load(0x449,&vm); xx = (word)VirtualScrCtrLUTx[vm]; yy = (word)VirtualScrCtrLUTy[vm]; // // The values for the confining virtual pixel coordinate rectangle // as set up by int 33h functions 7 and 8 are now released and the // default virtual bounds are used. // confine.bF7 = FALSE; // reset the flag indicating a int 33h function 7 confine.bF8 = FALSE; // reset the flag indicating a int 33h function 8 bFunctionZeroReset = TRUE; // // write the centre position data back to the 16 bit driver. // if(sc.ScreenState == FULLSCREEN) { // // Force a host_os_mouse_pointer call to do the // write back into the 16 bit driver. // LazyMouseInterrupt(); } #endif /*X86GFX */ // // Set the default Mickey to pixel ratios // This is set to 8 pixels to 8 Mickeys in the horizontal direction // and 16 pixels to 8 Mickeys in the vertical. // m2pX = 8; m2pY = 16; } GLOBAL void mouse_set_position IFN2(USHORT, newx, USHORT, newy) { #ifdef X86GFX word currentCS, currentIP, currentCX, currentDX; boolean currentIF; half_word internalCF; // // write the new position to the 16 bit driver for the fast // int33hf3 calls on X86. // sas_storew(effective_addr(button_seg,((word)(button_off+2))),(word)newx); sas_storew(effective_addr(button_seg,((word)(button_off+4))),(word)newy); #endif //X86GFX // // Both Fullscreen and MouseHidePointer enabled windowed mode // mouse emulations are driven by a set of emulated counters. // X,Y values are held independently to these counters and rely // on this function to set up absolute values for X and Y. Note: // reset does this too. // if(sc.ScreenState == WINDOWED && bPointerOff) { newF4x = (IS16)newx; newF4y = (IS16)newy; bFunctionFour = TRUE; return; } #ifdef X86GFX else if(sc.ScreenState == FULLSCREEN) { // // The values that are passed in are hot and fresh from the app. // Since they have not been tainted by the base, they are still // in virtual coordinates which is cool. // // // Get the internal cursor flag from the 16 bit driver // sas_load(mouseCFsysaddr,&internalCF); // // Only draw the pointer if the internal cursor flag // is zero. Note: less than zero == don't draw. // if(!internalCF) { /* if conditional off is diabled or the cursor is outside the * conditional off rectangle, move the cursor */ if (sas_hw_at_no_check(conditional_off_sysaddr) == 0 || !cursor_in_black_hole(newx, newy)) { currentCS=getCS(); currentIP=getIP(); currentCX=getCX(); currentDX=getDX(); currentIF=getIF(); setCS(DRAW_FS_POINTER_SEGMENT); // sacrificial data setIP(DRAW_FS_POINTER_OFFSET); setCX((word)newx); setDX((word)newy); setIF(FALSE); // // call back to 16bits move cursor code. // host_simulate(); // // Tidy up // setCX(currentCX); setDX(currentDX); setCS(currentCS); setIP(currentIP); setIF(currentIF); } else { /* the cursor was moved into the conditional rectangle, hide it */ sas_store(mouseCFsysaddr, 0xff); host_hide_pointer(); } } newF4x = (IS16)newx; newF4y = (IS16)newy; bFunctionFour = TRUE; // // update the last mouse position global locators // old_x = newx; old_y = newy; } #endif //X86GFX } GLOBAL void mouse_cursor_display() { } GLOBAL void mouse_cursor_undisplay() { } GLOBAL void mouse_cursor_mode_change() { } GLOBAL void host_mouse_conditional_off_enabled(void) { #ifdef X86GFX word x, y; /* hide the cursor if * (1). we are in full screen and * (2). the cursor is on and is in the conditional area */ if (sc.ScreenState == FULLSCREEN && !sas_hw_at_no_check(mouseCFsysaddr)) { x = sas_w_at_no_check(effective_addr(CP_X_S, CP_X_O)); y = sas_w_at_no_check(effective_addr(CP_Y_S, CP_Y_O)); if (cursor_in_black_hole(x, y)) { sas_store(mouseCFsysaddr, 0xff); host_hide_pointer(); } } #endif } //============================================================================== // Hook function that forms the communication transition between // the host and the base for os pointer emulation. This function // is called by mouse_int1() which lives in mouse_io.c //============================================================================== VOID host_os_mouse_pointer(MOUSE_CURSOR_STATUS *mcs,MOUSE_CALL_MASK *call_mask, MOUSE_VECTOR *counter) { #ifdef X86GFX sys_addr int33f3addr; #endif // X86GFX host_ica_lock(); // synch with the event thread GetNextMouseEvent(); #ifdef X86GFX if(sc.ScreenState == FULLSCREEN) { ScaleToFullscreenVirtualCoordinates(&mcs->position.x,&mcs->position.y,counter); } else #endif // X86GFX { ScaleToWindowedVirtualCoordinates(&mcs->position.x,&mcs->position.y,counter); } // // Create a condition mask for use by any call back installed // by the application. // AssembleCallMask(call_mask); // // Tell the base about the button state // mcs->button_status=os_pointer_data.button_l | os_pointer_data.button_r<<1; host_ica_unlock(); // synch with the event thread // // Has the pointer moved since the last mouse interrupt. // This can happen if a button press occurs but no physical // movement of the mouse body takes place. // if(bPointerInSamePlace) { // // The mouse has not moved since the last mouse // hardware interrupt. // *call_mask &= ~1; } else { #ifdef X86GFX half_word internalCF; #endif // X86GFX // // The mouse has moved. // *call_mask |= 1; #ifdef X86GFX // // Inquire from the 16 bit driver whether or not the // pointer can be drawn. // internalCF < 0 -> cannot draw // internalCF == 0 okay to draw. // sas_load(mouseCFsysaddr,&internalCF); // // If the system has fullscreen capabilities and is in fullscreen // mode, then if the pointer has been switched on, draw it on the // fullscreen display. // if(sc.ScreenState == FULLSCREEN && !internalCF) { half_word v; static half_word hwLastModeType; if (sas_hw_at_no_check(conditional_off_sysaddr) == 0 || !cursor_in_black_hole(mcs->position.x, mcs->position.y)) { // // Get the current BIOS video mode a la B.D.A. // sas_load(0x449,&v); if((hwLastModeType = TextOrGraphicsModeLUT[v]) == GRAPHICS_MODE) { word currentCS,currentIP; // save those interesting Intel registers word currentCX,currentDX; boolean currentIF; // // Do the host simulate here to draw the cursor image // for the full screen graphics // currentCS=getCS(); currentIP=getIP(); currentCX=getCX(); currentDX=getDX(); currentIF=getIF(); setCS(DRAW_FS_POINTER_SEGMENT); setIP(DRAW_FS_POINTER_OFFSET); setCX(mcs->position.x); setDX(mcs->position.y); setIF(FALSE); // // call to 16bits move cursor code // host_simulate(); // // Restore the 16 bit context. // setCX(currentCX); setDX(currentDX); setCS(currentCS); setIP(currentIP); setIF(currentIF); } else // TEXT_MODE { // // if there has been a switch from graphics mode to text mode // then there cannot have been a backround saved. // if(hwLastModeType == GRAPHICS_MODE) { bFullscTextBkgrndSaved = FALSE; hwLastModeType = TEXT_MODE; } // // Use some 32 bit code to draw the text pointer because // no hardware i/o is involved and we need only to write to // the display buffer (16 bit code is needed to do video // i/os in fullscreen mode). // FullscTextPtr(mcs->position.x,mcs->position.y); } } else { sas_store(mouseCFsysaddr, 0xff); host_hide_pointer(); } } #endif // X86GFX } // // Write data to the 16 bit driver for int 33h function 3 to pick up // without having to BOP to the 32 bit side. // Int 33h function 3 requires this data: // BX = button status // CX = virtual pixel position in x // DX = virtual pixel position in y // #ifdef X86GFX int33f3addr = effective_addr(button_seg,button_off); sas_storew(int33f3addr,mcs->button_status); sas_storew(int33f3addr+=2, (word)(mcs->position.x)); sas_storew(int33f3addr+=2, (word)(mcs->position.y)); #endif //X86GFX } //============================================================================== // Function to munge the status register value for the InPort adapter. // Nothing much else to say about it really. // //============================================================================== void AssembleCallMask(MOUSE_CALL_MASK *call_mask) { static int old_l_button=0; // previous mouse button state static int old_r_button=0; // // add in the left button current status // if(os_pointer_data.button_l) { // // Left button is down. // if(!old_l_button) { // // The button has just been pressed // *call_mask |= (1<<1); } else { // // The button was down on the last hardware interrupt, so // release the edge detect. // *call_mask &= ~(1<<1); } } else { // // Left button is up. // if(old_l_button) { // // The button has just been released // *call_mask |= (1<<2); } else { // // The button was up on the last hardware interrupt, so // release the edge detect. // *call_mask &= ~(1<<2); } } // // add in the right button current status // if(os_pointer_data.button_r) { // // Right button is down. // if(!old_r_button) { // // The button has just been pressed // *call_mask |= (1<<3); } else { // // The button was down on the last hardware interrupt, so // release the edge detect. // *call_mask &= ~(1<<3); } } else { // // Right button is up. // if(old_r_button) { // // The button has just been released // *call_mask |= (1<<4); } else { // // The button was up on the last hardware interrupt, so // release the edge detect. // *call_mask &= ~(1<<4); } } // // // save the current mouse button status. // old_l_button = os_pointer_data.button_l; old_r_button = os_pointer_data.button_r; } #ifdef X86GFX //========================================================================= // Function to scale mouse coordinates as retrieved from USER // to virtual coordinates as defined by the Microsoft Mouse // Programmer's Reference. //========================================================================= void ScaleToFullscreenVirtualCoordinates(IS16 *outx,IS16 *outy, MOUSE_VECTOR *counter) { half_word video_mode,textorgraphics; IS16 internalX = 0, internalY = 0; static IS16 lastinternalX=0, lastinternalY=0; POINT vector; // Magnitude and direction since last call // // Manage the system pointer so that it never sticks to a system // imposed boundary. Also get a relative displacement of the mouse. // FullscreenWarpSystemPointer(&vector); // // return the internal counter values back to the base // code for it to use to generate the counters there. // counter->x = (MOUSE_SCALAR)vector.x; counter->y = (MOUSE_SCALAR)vector.y; // // Get the current BIOS video mode from the B.D.A. This comes // in handy in a couple of places later. // sas_load(0x449,&video_mode); // // checkout some global flags with indicate if one of the int 33h // functions which are capable of changing the position of the // DOS mouse driver pointer have been called since the last mouse // hardware interrupt. // if(bFunctionZeroReset) { // // Calculate the centre of the default virtual screen // and set the current generated coordinates to it. // internalX = (IS16)VirtualScrCtrLUTx[video_mode]; internalY = (IS16)VirtualScrCtrLUTy[video_mode]; bFunctionZeroReset = FALSE; } else if(bFunctionFour) { // // The application has set the pointer to a new location. // Tell the internal cartesian coordinate system about this. // internalX = newF4x; // This is where the pointer was set to internalY = newF4y; // by the app on the last pending call to f4 // // Don't come in here again until the next function 4. // bFunctionFour = FALSE; } else { // // The most frequent case. Determine the new, raw pointer position // by adding the system pointer movement vector to the last position // of the emulated pointer. // internalX = lastinternalX + (IS16)vector.x; internalY = lastinternalY + (IS16)vector.y; } // // use the video mode to determine if we're running text or graphics // textorgraphics=TextOrGraphicsModeLUT[video_mode]; // // Scale the coordinates appropriately for the current video mode // and the type (text or graphics) that it is. // if(textorgraphics == TEXT_MODE) { // // The virtual cell block is 8 by 8 virtual pixels for any text mode. // This means that the cell coordinates in virtual pixels increments // by 8 in the positive x and y directions and the top left hand corner // of the cell starts at 0,0 and has the virtual pixel value for the // whole text cell. // TextScale(&internalX,&internalY,outx,outy); } else // GRAPHICS_MODE { LimitCoordinates(video_mode,&internalX,&internalY); *outx = internalX; *outy = internalY; } // // Set up the current emulated position for next time through // this function. // lastinternalX = internalX; lastinternalY = internalY; // // Signal that the pointer hasn't moved, if it hasn't // bPointerInSamePlace = (!vector.x && !vector.y) ? TRUE : FALSE; // // save the current position for next time. // old_x = *outx; old_y = *outy; } //============================================================================== // Function to make sure that the system pointer can be made to move in a // given cartesian direction without hitting and finite boundaries as specified // by the operating system. //============================================================================== void FullscreenWarpSystemPointer(POINT *vector) { static POINT pLast; // System pointer position data from last time through POINT pCurrent; // // Get a system mouse pointer absolute position value back from USER. // GetCursorPos(&pCurrent); // // Calculate the vector displacement of the system pointer since // the last call to this function. // vector->x = pCurrent.x - pLast.x; vector->y = pCurrent.y - pLast.y; // // Has the system pointer hit a border? If so, warp the system pointer // back to the convienient location of 0,0. // if(pCurrent.x >= (LONG)1000 || pCurrent.x <= (LONG)-1000 || pCurrent.y >= (LONG)1000 || pCurrent.y <= (LONG)-1000) { // // If the counters have warped, set the system pointer // to the relavent position. // SetCursorPos(0,0); pLast.x = 0L; // prevent a crazy warp pLast.y = 0L; } else { // // update the last position data of the // system pointer for next time through. // pLast = pCurrent; } } #endif // X86GFX //========================================================================= // Function to scale mouse coordinates as returned by the event loop // mechanism to virtual coordinates as defined by the Microsoft Mouse // Programmer's Reference. The method used for scaling depends on the style // of mouse buffer selected, the current video mode and if (for X86) the // video system is operating in full screen or windowed mode. // // Output: Virtual cartesian coordinates in the same pointers //========================================================================= void ScaleToWindowedVirtualCoordinates(IS16 *outx,IS16 *outy, MOUSE_VECTOR *counter) { half_word video_mode,textorgraphics; SAVED SHORT last_text_good_x = 0, last_text_good_y = 0; sas_load(0x449,&video_mode); // // Follow different code paths if the user has the system pointer // hidden or displayed. // if(!bPointerOff) { // // The pointer has not been hidden by the user, so use the // x,y values as got from the system pointer via the Windows // messaging system. // // // get the video mode to determine if we're running text or graphics // textorgraphics=TextOrGraphicsModeLUT[video_mode]; if(textorgraphics == TEXT_MODE) { // // validate received data to ensure not graphics mode coords // received during mode switch. // if(os_pointer_data.x > 87) { *outx = last_text_good_x; } else { *outx = ConsoleTextCellToVPCellLUT[os_pointer_data.x]; last_text_good_x = *outx; } if(os_pointer_data.y > 87) { *outy = last_text_good_y; } else { *outy = ConsoleTextCellToVPCellLUT[os_pointer_data.y]; last_text_good_y = *outy; } } else // GRAPHICS_MODE { // // If the mouse is NOT in a warping mode, then x,y's as received // from the console are scaled if they are for a low resolution // video mode and these are what the application sees and the // system pointer image is in the correct place to simulate the // 16 bit pointer. // If the application decides to extend the x,y bounds returned // from the driver beyond the limits of the console being used, // these x,y's are not appropriate, and the mouse must be switched // into warp mode by the user and the code will emulate the x,y // generation. // WindowedGraphicsScale(video_mode,(IS16)(os_pointer_data.x), (IS16)(os_pointer_data.y),outx,outy); } // // No warping, so set up the old_x and old_y values directly. // Signal that the pointer hasn't moved, if it hasn't // bPointerInSamePlace = (old_x == *outx && old_y == *outy) ? TRUE : FALSE; // // Set these statics for the next time through. // old_x = *outx; old_y = *outy; } else { // // The user has set the system pointer to be hidden via the // console's system menu. // Handle by emulating the counters and generating absolute x,y // data from this. // IS16 move_x,move_y; // // Get positional data from the system pointer and maintain some // counters. // if(WarpSystemPointer(&move_x,&move_y)) { // // The mouse moved. // Generate some new emulated absolute position information. // EmulateCoordinates(video_mode,move_x,move_y,outx,outy); // // Save up the current emulated position for next time through. // old_x = *outx; old_y = *outy; // // Send back the relative motion since last time through. // counter->x = move_x; counter->y = move_y; bPointerInSamePlace = FALSE; } else { // // No recorded movement of the mouse. // *outx = old_x; *outy = old_y; counter->x = counter->y = 0; bPointerInSamePlace = TRUE; } } } //============================================================================== // Function to scale the incoming fullscreen coordinates to mouse motion (both // absolute and relative) for fullscreen text mode. // Note: if the application chooses to, it can reset the virtual coordinate // bounds of the virtual screen. This function checks the bound flags and either // selects the default values or the app imposed values. // // This function is also used to modify the coordinates produced directly from // the motion counters in windowed text mode. //============================================================================== void TextScale(IS16 *iX,IS16 *iY,IS16 *oX, IS16 *oY) { half_word no_of_rows; // // Calculate the current system pointer location in virtual // pixels for the application. // if(confine.bF7) { // // Limits have been imposed by the application. // if(*iX < confine.xmin) { *iX = confine.xmin; } else if(*iX > confine.xmax) { *iX = confine.xmax; } } else // use the default virtual screen constraints. { // // No limits have been imposed by the application. // x is always 0 -> 639 virtual pixels for text mode // if(*iX < 0) { *iX = 0; } else if(*iX > 639) { *iX = 639; } } // // Bind the y cartesian coordinate appropriately // if(confine.bF8) { // // Limits have been imposed by the application. // if(*iY < confine.ymin) { *iY = confine.ymin; } else if(*iY > confine.ymax) { *iY = confine.ymax; } } else { // // The application has not imposed constraints on the Y virtual pixel // motion, so confine the Y movement to the default virtual pixel size // of the virtual screen for the current video mode. // if(*iY < 0) { *iY = 0; } else { // // Get the number of text rows minus one, from the B.D.A. // sas_load(0x484,&no_of_rows); switch(no_of_rows) { case 24: { // // 25 rows, so there are 200 vertical virtual pixels // if(*iY > 199) { *iY = 199; } break; } case 42: { // // 43 rows, so there are 344 vertical virtual pixels // if(*iY > 343) { *iY = 343; } break; } case 49: { // // 50 rows, so there are 400 vertical virtual pixels // if(*iY > 399) { *iY = 399; } break; } default: { // // default - assume 25 rows, so there are // 200 vertical virtual pixels // if(*iY > 199) { *iY = 199; } break; } } } } *oX = *iX; *oY = *iY; } //============================================================================== // Fit the raw x,y coordinates generated from the counters to the bounds of // the virtual screen that is currently set up. This can be set up either by // the application (in the confine structure) or as set by the mouse driver // as default. //============================================================================== void LimitCoordinates(half_word vm,IS16 *iX,IS16 *iY) { // // Select the appropriate conditioning code for // the current video mode. // switch(vm) { // // Do the common text modes. // case(2): case(3): case(7): { IS16 oX,oY; // // Scale the generated coordinates for the given text mode // and the number of rows of text displayed on the screen. // TextScale(iX,iY, &oX, &oY); *iX = oX; *iY = oY; break; } // // The regular VGA supported graphics video modes. // // The following modes are all 640 x 200 virtual pixels // case(4): case(5): case(6): case(0xd): case(0xe): case(0x13): { if(confine.bF7) { // // Limits have been imposed by the application. // if(*iX < confine.xmin) { *iX = confine.xmin; } else if(*iX > confine.xmax) { *iX = confine.xmax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; } if(confine.bF8) { // // Limits have been imposed by the application. // if(*iY < confine.ymin) { *iY = confine.ymin; } else if(*iY > confine.ymax) { *iY = confine.ymax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iY < 0) *iY = 0; else if(*iY > 199) *iY = 199; } break; } // // The following modes are all 640 x 350 virtual pixels // case(0xf): case(0x10): { if(confine.bF7) { // // Limits have been imposed by the application. // if(*iX < confine.xmin) { *iX = confine.xmin; } else if(*iX > confine.xmax) { *iX = confine.xmax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; } if(confine.bF8) { // // Limits have been imposed by the application. // if(*iY < confine.ymin) { *iY = confine.ymin; } else if(*iY > confine.ymax) { *iY = confine.ymax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iY < 0) *iY = 0; else if(*iY > 349) *iY = 349; } break; } // // The following modes are all 640 x 480 virtual pixels // case(0x11): case(0x12): { if(confine.bF7) { // // Limits have been imposed by the application. // if(*iX < confine.xmin) { *iX = confine.xmin; } else if(*iX > confine.xmax) { *iX = confine.xmax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; } if(confine.bF8) { // // Limits have been imposed by the application. // if(*iY < confine.ymin) { *iY = confine.ymin; } else if(*iY > confine.ymax) { *iY = confine.ymax; } } else { // // The application has not imposed limits, so use // the default virtual screen bounds as defined byt // the mouse driver. // if(*iY < 0) *iY = 0; else if(*iY > 479) *iY = 479; } break; } // // From here on down are the Video7 modes // case(0x60): { if(*iX < 0) *iX = 0; else if(*iX > 751) *iX = 751; if(*iY < 0) *iY = 0; else if(*iY > 407) *iY = 407; break; } case(0x61): { if(*iX < 0) *iX = 0; else if(*iX > 719) *iX = 719; if(*iY < 0) *iY = 0; else if(*iY > 535) *iY = 535; break; } case(0x62): case(0x69): { if(*iX < 0) *iX = 0; else if(*iX > 799) *iX = 799; if(*iY < 0) *iY = 0; else if(*iY > 599) *iY = 599; break; } case(0x63): case(0x64): case(0x65): { if(*iX < 0) *iX = 0; else if(*iX > 1023) *iX = 1023; if(*iY < 0) *iY = 0; else if(*iY > 767) *iY = 767; break; } case(0x66): { if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; if(*iY < 0) *iY = 0; else if(*iY > 399) *iY = 399; break; } case(0x67): { if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; if(*iY < 0) *iY = 0; else if(*iY > 479) *iY = 479; break; } case(0x68): { if(*iX < 0) *iX = 0; else if(*iX > 719) *iX = 719; if(*iY < 0) *iY = 0; else if(*iY > 539) *iY = 539; break; } default: { if(*iX < 0) *iX = 0; else if(*iX > 639) *iX = 639; if(*iY < 0) *iY = 0; else if(*iY > 199) *iY = 199; break; } } } //============================================================================== // Function to scale the incoming windowed coordinates since the window size // can be larger (for the low resolution modes) than the virtual screen size // for that mode. //============================================================================== void WindowedGraphicsScale(half_word vm,IS16 iX,IS16 iY,IS16 *oX, IS16 *oY) { switch(vm) { // // The following modes are all 640 x 200 virtual pixels // case(4): case(5): case(6): case(0xd): case(0xe): case(0x13): { // // Low resolution graphics modes. The window is 640 x 400 real host // pixels, but the virtual screen resolution is 640 x 200. Hence // must divide the y value by 2 to scale appropriately. // iY >> 1; break; } } // // prepare the cartesian coordinate values to return. // *oX = iX; *oY = iY; } //=========================================================================== // Function to turn on the mouse cursor in FULLSCREEN mode. // Note: This function only gets called after the 16 bit code checks // to see if the internal cursor flag is zero. The 16 bit code does // not do the BOP if, after incrementing this counter, the above is // true. //=========================================================================== void host_show_pointer() { #ifdef X86GFX if(sc.ScreenState == FULLSCREEN) { half_word v; sas_load(0x449,&v); if(TextOrGraphicsModeLUT[v] == GRAPHICS_MODE) { word currentCS,currentIP; // save those interesting Intel registers boolean currentIF; sas_storew(effective_addr(CP_X_S,CP_X_O),(word)old_x); sas_storew(effective_addr(CP_Y_S,CP_Y_O),(word)old_y); currentCS=getCS(); currentIP=getIP(); currentIF=getIF(); setCS(POINTER_ON_SEGMENT); setIP(POINTER_ON_OFFSET); setIF(FALSE); host_simulate(); setCS(currentCS); setIP(currentIP); setIF(currentIF); } else //TEXT_MODE { FullscTextPtr(old_x,old_y); } LazyMouseInterrupt(); } #endif // X86GFX } //=========================================================================== // Function to turn off the mouse cursor in FULLSCREEN mode. // Note: This function only gets called after the 16 bit code checks // to see if the internal cursor flag is zero. The 16 bit code does // not do the BOP if, after decrementing this counter, the above is // true. //=========================================================================== void host_hide_pointer() { #ifdef X86GFX if(sc.ScreenState == FULLSCREEN) { half_word v; sas_load(0x449,&v); if(TextOrGraphicsModeLUT[v] == GRAPHICS_MODE) { word currentCS,currentIP; // save those interesting Intel registers boolean currentIF; currentCS=getCS(); currentIP=getIP(); currentIF=getIF(); setCS(POINTER_OFF_SEGMENT); setIP(POINTER_OFF_OFFSET); setIF(FALSE); host_simulate(); setCS(currentCS); setIP(currentIP); setIF(currentIF); } else //TEXT_MODE { if(bFullscTextBkgrndSaved) { sas_storew(old_text_addr,text_ptr_bkgrnd); bFullscTextBkgrndSaved = FALSE; } } LazyMouseInterrupt(); } #endif // X86GFX } //========================================================================= // Function to remove the mouse pointer item from the console system menu // when SoftPC lets an application quit or iconise. // If the system pointer is OFF i.e. clipped to a region in the current window, // then relinquish it to the system. // // bForce allows the code which gets called when there is a fullscreen to // windowed graphics switch on x86 to force the menu item off. //========================================================================= void MouseDetachMenuItem(BOOL bForce) { if(bMouseMenuItemAdded || bForce) { DeleteMenu(hM,IDM_POINTER,MF_BYCOMMAND); bMouseMenuItemAdded=FALSE; ClipCursor(NULL); } bAlertMessage=TRUE; // blocking, so reset the int33h f11 alert mechanism } void MouseAttachMenuItem(HANDLE hBuff) { if(!bMouseMenuItemAdded) { // // Read in the relavent string from resource // hM = ConsoleMenuControl(hBuff,IDM_POINTER,IDM_POINTER); AppendMenu(hM,MF_STRING,IDM_POINTER,szHideMouseMenuStr); bMouseMenuItemAdded=TRUE; // // initial state -> system pointer is ON // bPointerOff=FALSE; } } //========================================================================= // Function to determine if the active output buffer has changed if the VDM // has done something weird like resized or gone from graphics to fullscreen // or vice versa. If so, a new handle to the new buffer must be got, and the // old menu item deleted and a new menu item attach so that the new buffer // "knows" about the menu item I.D. //========================================================================= void MouseReattachMenuItem(HANDLE hBuff) { static HANDLE hOld = 0; // The handle for the last buffer selected. // // If the output buffer has not changed, then don't do anything. // if(hOld == hBuff) return; // // First thing, remove the old menu item. // MouseDetachMenuItem(TRUE); // // Next, Add in the new menu item for the current buffer. // MouseAttachMenuItem(hBuff); // // Record the value of the latest buffer for next time. // hOld = hBuff; } void MouseHide(void) { ModifyMenu(hM,IDM_POINTER,MF_BYCOMMAND,IDM_POINTER, (LPTSTR)szDisplayMouseMenuStr); // // Clip the pointer to a region inside the console window // and move the pointer to the window centre // while(ShowConsoleCursor(sc.ActiveOutputBufferHandle,FALSE)>=0) ; MovePointerToWindowCentre(); bPointerOff=TRUE; } void MouseDisplay(void) { ModifyMenu(hM,IDM_POINTER,MF_BYCOMMAND,IDM_POINTER, (LPTSTR)szHideMouseMenuStr); // // Let the pointer move anywhere on the screen // ClipCursor(NULL); while(ShowConsoleCursor(sc.ActiveOutputBufferHandle,TRUE)<0) ; bPointerOff=FALSE; } void MovePointerToWindowCentre(void) { RECT rTemp; // // Get current console client rectangle, set the clipping region to match // the client rect. Retrieve the new clipping rect from the system (is // different from what we requested!) and save it. // VDMConsoleOperation(VDM_CLIENT_RECT,&WarpClientRect); rTemp = WarpClientRect; CToS(&rTemp); ClipCursor(&rTemp); GetClipCursor(&WarpBorderRect); // // Note : LowerRight clip point is exclusive, UpperLeft point is inclusive // WarpBorderRect.right--; WarpBorderRect.bottom--; pMiddle.x = ((WarpBorderRect.right - WarpBorderRect.left)>>1) +WarpBorderRect.left; pMiddle.y = ((WarpBorderRect.bottom - WarpBorderRect.top)>>1) +WarpBorderRect.top; // // move the pointer to the centre of the client area // SetCursorPos((int)pMiddle.x,(int)pMiddle.y); // // Prevent the next counter calculation from resulting in a // large warp. // pLast = pMiddle; } //============================================================================= // Function to convert a rectangle structure from client coordinates to // screen coordinates. //============================================================================= void CToS(RECT *r) { POINT pt; // // Sort out the top, lefthand corner of the rectangle. // pt.x = r->left; pt.y = r->top; VDMConsoleOperation(VDM_CLIENT_TO_SCREEN,(LPVOID)&pt); r->left = pt.x; r->top = pt.y; // // Now do the bottom, right hand corner. // pt.x = r->right; pt.y = r->bottom; VDMConsoleOperation(VDM_CLIENT_TO_SCREEN,(LPVOID)&pt); r->right = pt.x; r->bottom = pt.y; } //============================================================================= // // Function - EmulateCoordinates. // Purpose - When the mouse is hidden by the user in windowed mode, this // function generate absolute x,y values from the relative motion // of the system pointer between mouse hardware interrupts // // Returns - Nothing. // // // // Author - Andrew Watson. // Date - 19-Mar-1994. // //============================================================================= void EmulateCoordinates(half_word video_mode,IS16 move_x,IS16 move_y,IS16 *x,IS16 *y) { static IS16 lastinternalX=0,lastinternalY=0; IS16 internalX,internalY; // // If the application has reset the mouse, set the x,y position to // the centre of the default virtual screen for the current video mode. // if(bFunctionZeroReset) { // // Calculate the centre of the default virtual screen // and set the current generated coordinates to it. // internalX = (VirtualX >> 1) - 1; internalY = (VirtualY >> 1) - 1; bFunctionZeroReset = FALSE; } else if(bFunctionFour) { // // The application has set the pointer to a new location. // Tell the counter emulation about this. // internalX = newF4x; internalY = newF4y; // // Don't come in here again until the next function 4. // bFunctionFour = FALSE; } else { // // Generate the new x,y position based on the counter change and // clip to whatever boundary (default or application imposed) has // been selected. // internalX = lastinternalX + move_x; internalY = lastinternalY + move_y; LimitCoordinates(video_mode,&internalX,&internalY); } // // Set up the current emulated position for next time through // this function. // lastinternalX = internalX; lastinternalY = internalY; // // set up the return x,y values. // *x = internalX; *y = internalY; } //============================================================================= // Function which hooks into the base mechanism for dealing with int 33h and // catches the function (AX=0xf) when the application tries to set the default // mickey to pixel ratio. //============================================================================= void host_m2p_ratio(word *a, word *b, word *CX, word *DX) { m2pX = *(short *)CX; m2pY = *(short *)DX; } //============================================================================= // // Function - WarpSystem Pointer // Purpose - Allows movement vectors to be calculated from the movement of // the operating system pointer. This function will not let the // the system pointer move out of the client area. This, plus the // warping mechanism ensures that the emulated pointer can move // forever in any given direction. // // Returns - TRUE if the system pointer has moved, FALSE if not. // // // // Author - Andrew Watson. // Date - 19-Mar-1994. // //============================================================================= BOOL WarpSystemPointer(IS16 *move_x,IS16 *move_y) { POINT pt; // // Is the Console window in the same place or changed // Update the client rect data accordingly // HasConsoleClientRectChanged(); // // Get the current position of the system pointer // GetCursorPos(&pt); // // How far has the system pointer moved since the last call. // *move_x = (IS16)(pt.x - pLast.x); *move_y = (IS16)(pt.y - pLast.y); // // Do a fast exit if no movement has been determined. // if(*move_x || *move_y) { // // The system mouse pointer has moved. // See if the pointer has reached the client area boundary(s) // if(pt.y <= WarpBorderRect.top || pt.y >= WarpBorderRect.bottom || pt.x >= WarpBorderRect.right || pt.x <= WarpBorderRect.left) { // // if the boundary(s) was/were met, warp the pointer to the // client area centre. // SetCursorPos((int)pMiddle.x,(int)pMiddle.y); // // The current position is now the centre of the client rectangle. // Save this as the counter delta start point for next time. // pLast = pMiddle; } else { // // There wasn't a warp. // Update the last known position data for next time through. // pLast = pt; } // // The cursor has to moved as determined from the previous and current // system pointer positions. // return TRUE; } // // No movement, so return appropriately. // return FALSE; } //============================================================================== // Function to detect if the Console window has moved/resized. If it has, this // function updates the WarpBorderRect and the pMiddle structures to reflect // this. // // Returns TRUE if moved/resized, FALSE if not. //============================================================================== BOOL HasConsoleClientRectChanged(void) { RECT tR; // // If console client rectangle has changed, reset the mouse clipping // else nothing to do! // VDMConsoleOperation(VDM_CLIENT_RECT,&tR); if (tR.top != WarpClientRect.top || tR.bottom != WarpClientRect.bottom || tR.right != WarpClientRect.right || tR.left != WarpClientRect.left) { CToS(&tR); #ifdef MONITOR // // Is the warp region an Icon in fullscreen graphics? // Note: An icon has a client rect of 36 x 36 pixels. // if((tR.right - tR.left) == 36 && (tR.bottom - tR.top) == 36) { // // Make the warp region the same size as the selected buffer. // The warp rectangle is thus originated about the top, left // hand corner of the screen. // tR.top = 0; tR.bottom = mouse_buffer_height; tR.left = 0; tR.right = mouse_buffer_width; CToS(&tR); } #endif //MONITOR // // Clip the pointer to the new client rectangle, and retrive // the new clipping borders. // ClipCursor(&tR); GetClipCursor(&WarpBorderRect); // // Note: LowerRight clip point is exclusive, UpperLeft point is inclusive // WarpBorderRect.right--; WarpBorderRect.bottom--; // // determine the middle point in the new client rectangle // pMiddle.x = ((WarpBorderRect.right - WarpBorderRect.left)>>1) +WarpBorderRect.left; pMiddle.y = ((WarpBorderRect.bottom - WarpBorderRect.top)>>1) +WarpBorderRect.top; return TRUE; } return FALSE; } //============================================================================== // Focus sensing routines for the pointer clipping system. Focus events come // via the main event loop where the following two modules are called. If // the application is using int33hf11, this is detected, and on focus gain or // loss, the routines clip or unclip the pointer to the console window. //============================================================================== void MouseInFocus(void) { MouseAttachMenuItem(sc.ActiveOutputBufferHandle); // // only do when app. uses int33hf11 // if(!bPointerOff) return; MovePointerToWindowCentre(); // // Lose system pointer image again // ShowConsoleCursor(sc.ActiveOutputBufferHandle, FALSE); } void MouseOutOfFocus(void) { // // only do when app. uses int33hf11 // if(!bPointerOff) { MouseDetachMenuItem(FALSE); return; } // // Clip the pointer to the whole world (but leave its mother alone) // ClipCursor(NULL); // // Re-enable system pointer image // ShowConsoleCursor(sc.ActiveOutputBufferHandle, TRUE); } /* system memu active, stop cursor clipping */ void MouseSystemMenuON (void) { if (bPointerOff) ClipCursor(NULL); } /* system menu off, restore clipping */ void MouseSystemMenuOFF(void) { if (bPointerOff) ClipCursor(&WarpBorderRect); } void ResetMouseOnBlock(void) { host_ica_lock(); os_pointer_data.x=0; os_pointer_data.y=0; host_ica_unlock(); } #ifdef X86GFX //============================================================================ // Function which is called from the 32 bit side (x86 only) when there is // a transition from fullscreen text to windowed text. The function restores // the background to the last mouse pointer position. This stops a pointer // block from remaining in the image, corrupting the display when the system // pointer is being used. // // This function looks into the 16 bit driver's space and points to 4, 16 bit // words of data from it, viz: // // dw offset of pointer into video buffer. // dw unused. // dw image data to be restored. // dw flag = 0 if the background is stored // // Note: that during a fullscreen switch, 16 bit code cannot be executed, // thus the patching of the buffer is done here. //============================================================================ void CleanUpMousePointer() { half_word vm; // // Only execute this routine fully if in TEXT mode // sas_load(0x449,&vm); // Get the current video mode according to the B.D.A. if(TextOrGraphicsModeLUT[(int)vm] != TEXT_MODE) return; // // If there is a backround stored for the text pointer when it was // in fullscreen land, then restore it to the place it came from // when windowed. // if(bFullscTextBkgrndSaved) { sas_storew(old_text_addr,text_ptr_bkgrnd); // // No background saved now. // bFullscTextBkgrndSaved = FALSE; } } #endif //X86GFX //=========================================================================== // Function to display the text cursor image for fullscreen text mode. // INPUT: x,y pointer virtual cartesian coordinates for text screen buffer. // Note: the Y coordinates are received in the sequence 0, 8, 16, 24, 32, ... // since a virtual text cell is 8 virtual pixels square. //=========================================================================== void FullscTextPtr(int x,int y) { #ifdef X86GFX sys_addr text_addr; word current_display_page; // // Work out the offset to the current video display page. // Grovel around the B.D.A. to find out where the page starts. // sas_loadw(effective_addr(0x40,0x4e),¤t_display_page); x = (int)((DWORD)x & 0xFFFFFFF8); y = (int)((DWORD)y & 0xFFFFFFF8); // // save the character cell behind the next pointer // Note: The text cell offset calculated below is based on // the following concepts: // The virtual character cell size is 8 x 8 virtual pixels. // The input data to this function is in virtual pixels. // There are 80 text cells in a row = 80 (CHAR:ATTR) words. // The >>3<<1 on the x value ensures that the location // in the buffer to be modified occurs on a word boundary to // get the masking correct! // x &= 0xfffc; // remove the top to prevent funny shifts. x >>= 2; // get the word address for the current row y &= 0xffff; // work out the total number of locations for all the y rows y *= 20; // // // Generate the address in the display buffer at which the pointer // should be drawn. // text_addr = effective_addr(0xb800,(word)(current_display_page + x + y)); // assemble the cell address // // only restore the background if there is a background to restore! // if(bFullscTextBkgrndSaved) { sas_storew(old_text_addr,text_ptr_bkgrnd); } // // Load up the background from the new address // sas_loadw(text_addr,&text_ptr_bkgrnd); // read from that place bFullscTextBkgrndSaved=TRUE; // // Write the pointer to the video buffer. // Use some standard masks and forget what the app wants to // do cos that really isn't important and it's slow plus not // very many apps want to change the text pointer shape anyway. // sas_storew(text_addr,(word)((text_ptr_bkgrnd & 0x77ff) ^ 0x7700)); // // save the static variables to be used next time through the routine // old_text_addr=text_addr; #endif // X86GFX } //============================================================================== // Function to get the maximum and minimum possible virtual pixel locations // in X as requested by the application through int 33h function 7. //============================================================================== void host_x_range(word *blah, word *blah2,word *CX,word *DX) { confine.bF7 = TRUE; confine.xmin = *CX; confine.xmax = *DX; // // Force a mouse interrupt to make it happen. // LazyMouseInterrupt(); } //============================================================================== // Function to get the maximum and minimum possible virtual pixel locations // in Y as requested by the application through int 33h function 8. //============================================================================== void host_y_range(word *blah, word *blah2,word *CX,word *DX) { confine.bF8 = TRUE; confine.ymin = *CX; confine.ymax = *DX; // // Force a mouse interrupt to make it happen. // LazyMouseInterrupt(); } /* * LazyMouseInterrupt - * */ void LazyMouseInterrupt(void) { host_ica_lock(); if (!bMseEoiPending && !bSuspendMouseInterrupts) { if (MseIntLazyCount) MseIntLazyCount--; bMseEoiPending = TRUE; ica_hw_interrupt(AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT,1); HostIdleNoActivity(); } else if (!MseIntLazyCount) { MseIntLazyCount++; } host_ica_unlock(); } /* SuspendMouseInterrupts * * Prevents Mouse Interrupts from occuring until * ResumeMouseInterrupts is called * */ void SuspendMouseInterrupts(void) { host_ica_lock(); bSuspendMouseInterrupts = TRUE; host_ica_unlock(); } /* * ResumeMouseInterrupts * */ void ResumeMouseInterrupts(void) { host_ica_lock(); bSuspendMouseInterrupts = FALSE; if (!bMseEoiPending && (MseIntLazyCount || MoreMouseEvents()) ) { if (MseIntLazyCount) MseIntLazyCount--; bMseEoiPending = TRUE; host_DelayHwInterrupt(9, // AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT 1, // count 10000 // Delay ); HostIdleNoActivity(); } host_ica_unlock(); } /* * DoMouseInterrupt, assumes we are holding the ica lock * */ void DoMouseInterrupt(void) { if (bMseEoiPending || bSuspendMouseInterrupts) { MseIntLazyCount++; return; } if (MseIntLazyCount) MseIntLazyCount--; bMseEoiPending = TRUE; ica_hw_interrupt(AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT,1); HostIdleNoActivity(); } /* * MouseEoiHook, assumes we are holding the ica lock * */ VOID MouseEoiHook(int IrqLine, int CallCount) { if (CallCount < 0) { // interrupts were cancelled MseIntLazyCount = 0; FlushMouseEvents(); bMseEoiPending = FALSE; return; } if (!bSuspendMouseInterrupts && (MseIntLazyCount || MoreMouseEvents())) { if (MseIntLazyCount) MseIntLazyCount--; bMseEoiPending = TRUE; host_DelayHwInterrupt(9, // AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT 1, // count 10000 // Delay usecs ); HostIdleNoActivity(); } else { bMseEoiPending = FALSE; } }