📄 cursor.cpp
字号:
//A unique feature of Cursor routine is the requirement to handle
//dual-head virtual display environment. As user moves cursor from one
//display, say CRT, to another display, say LCD, we need to maintain
//cursor's smoothness at the boundary of two displays. To achieve that,
//Horizontal Cursor Offset and Vertical Cursor Offset of the 2nd display
//require to be adjusted accordingly.
#include "precomp.h"
// Customization options
// - comment out if no LargeDesktop support to save code size
//#define SUPPORT_LARGE_DESKTOP
// Handy equates
#define BG_BLACK 0x00FFFFFF
#define BG_WHITE 0x00000000
extern PALETTEENTRY _rgbIdentity2[];
extern PALETTEENTRY _rgbIdentity4[];
extern PALETTEENTRY _rgbIdentity16[];
#define VC_OFFSET_BUG
//extern BOOL bNoCursorShape;
// This function sets the shape of the pointer, the hot spot of the pointer,
// and (if it is multicolored) the colors to use for the cursor.
// GPE::MovePointer is called separately to move and/or hide the cursor.
// Remember, only one hardware cursor area is used.
//
SCODE
MQGC::SetPointerShape(
GPESurf *pMask,
GPESurf *pColorSurf,
int xHot,
int yHot,
int cx,
int cy )
{
unsigned short shapeRow[8]; //buffer to contain alternates of AND/XOR words
//(AND word, XOR word, AND word...)
int count, row, col;
unsigned short *pAndDst;
unsigned short *pXorDst;
unsigned short bitMask;
int y, x;
ULONG *pULONG;
ULONG ulData;
unsigned short ANDWord, XORWord;
// Set up cursor color
//
SetCursorColors();
// pWord point to cursor area which is common to GC1 and GC2
//
pULONG = (ULONG *)(&m_pLAW[m_nCursorStart << 10]);
if( cy == 0 )
{
m_nXHot = 32;
m_nYHot = 32; // we rely on MovePointer being called after this
for( y=0; y<64; y++ ) // Set up a default crosshair cursor
{
for( x=0; x<4; x++ )
{
if( y == 32 )
XORWord = 0xFFFF;
else
if( x == 1 )
XORWord = 0x0300;
else
XORWord = 0;
ANDWord = 0xFFFF;
ulData = (ULONG)XORWord;
ulData <<= 16;
ulData |= ANDWord;
*pULONG++ = ulData;
}
}
}
else
{
// initialize entire 64 x 64 shape to be ANDs=0xFFFF and XORs = 0x0000 (i.e. transparent)
m_nXHot = xHot;
m_nYHot = yHot; // we rely on MovePointer being called after this
for( row=0; row<64; row++ )
{
// Clear the row
for( count=0; count < 8; count+=2 )
{
shapeRow[count] = 0xFFFF;
shapeRow[count+1] = 0x0000;
}
if( row < cy )
{
// Write available bits into shapeRow
pAndDst = shapeRow;
pXorDst = pAndDst+1;
bitMask = 0x0001; // Starting here achieves byte swapping
for( col=0; col<cx; col++ )
{
if( !((((unsigned char *)pMask->Buffer())+row*pMask->Stride())[col/8] & ( 1 << (7-(col%8)) )) )
*pAndDst ^= bitMask;
if( ((((unsigned char *)pMask->Buffer())+(cy+row)*pMask->Stride())[col/8] & ( 1 << (7-(col%8)) )) )
*pXorDst ^= bitMask;
bitMask <<= 1;
if( !bitMask )
{
bitMask = 0x0001;
pAndDst += 2;
pXorDst += 2;
}
}
}
for( x=0; x<8; x+=2 )
{
ulData = (ULONG)shapeRow[x+1];
ulData <<= 16;
ulData |= shapeRow[x];
*pULONG++ = ulData;
}
}
}
return S_OK;
}
// This method is called to move the hot spot of the cursor to a
// specific x,y location or (if x==-1) to hide the cursor.
// - Special case has to be taken to handle cross-screen cursor movement
// at QView Large Desktop configuration.
//
SCODE MQGC::MovePointer(
int x,
int y )
{
ULONG ulTemp;
if (CursorData.ulFlag & GHOST_MODE_ACTIVE)
{
if (CursorData.ulFlag & SAME_IMAGE)
{
// Disable GC1 cursor
//
ulTemp = gc1READ(GC1_CONTROL) & HC_DISABLE;
gc1REG(GC1_CONTROL, ulTemp);
MovePointer1GC(x, y, 2);
}
else
{
//MovePointer1GC(x, y, 1);
// Need to use GC1 for external CRT
ulTemp = gc1READ(GC1_CONTROL) & HC_DISABLE;
gc1REG(GC1_CONTROL, ulTemp);
MovePointer1GC(x, y, 5);
}
}
else
if (!(CursorData.ulFlag & USE_2GCs_MASK))
MovePointer1GC(x, y, 1);
else
if (CursorData.ulFlag & SAME_IMAGE)
MovePointerSameImage(x, y);
#ifdef SUPPORT_LARGE_DESKTOP
else
if (CursorData.ulFlag & LARGE_DESKTOP)
MovePointerLD(x, y);
#endif // SUPPORT_LARGE_DESKTOP
DumpCursor();
return S_OK;
}
// This routine handle LCD-only CRT-only ans Simultaneous LCD/CRT
//
SCODE MQGC::MovePointer1GC(
int x,
int y,
int flag)
{
ULONG ulCurPos1, ulCurAddr1;
ULONG ulGC1Delta, ulTemp;
UpdateCursorVP(x,y,flag);
if (x == -1)
{
// Disable cursor
//
if (flag == 1)
{
ulTemp = gc1READ(GC1_CONTROL) & HC_DISABLE;
gc1REG(GC1_CONTROL, ulTemp);
}
else
{
ulTemp = gc2READ(GC2_CONTROL) & HC_DISABLE;
gc2REG(GC2_CONTROL, ulTemp);
}
}
if (flag == 1)
{
// Adjust cursor position
x -= CursorData.usGC1VPL;
y -= CursorData.usGC1VPT;
// Adjust for panning
ulGC1Delta = CursorData.usGC1VPT * m_ulScreenStride +
CursorData.usGC1VPL * m_nBytesPerPixel;
gc1REG(IW1_START_ADDR, m_nIW1StartAddr + ulGC1Delta);
}
else
{
if (flag == 5)
{
// Adjust cursor position
x -= CursorData.usGC1VPL;
y -= CursorData.usGC1VPT;
// Adjust for panning
ulGC1Delta = CursorData.usGC1VPT * m_ulScreenStride +
CursorData.usGC1VPL * m_nBytesPerPixel;
gc2REG(IW2_START_ADDR, m_nIW1StartAddr + ulGC1Delta);
}
else
{
// Adjust cursor position
x -= CursorData.usGC2VPL;
y -= CursorData.usGC2VPT;
// Adjust for panning
ulGC1Delta = CursorData.usGC2VPT * m_ulScreenStride +
CursorData.usGC2VPL * m_nBytesPerPixel;
gc2REG(IW2_START_ADDR, m_nIW2StartAddr + ulGC1Delta);
}
}
int newx = x - m_nXHot; // Hot spot is currently 32,32
int newy = y - m_nYHot;
int dx = 0;
int dy = 0;
if( newx < 0 )
{
dx = -newx;
newx = 0;
}
if( newy < 0 )
{
dy = -newy;
newy = 0;
}
// Set up cursor position and offset variables
//
#ifdef VC_OFFSET_BUG
if (dy == 63)
dy--;
#endif
ulCurPos1 = ((ULONG)newy << 16) | newx;
ulCurAddr1 = ((ULONG)dy << 24) | ((ULONG)dx << 16) | m_nCursorStart;
if (flag == 1)
{
gc1REG(HW_CURSOR1_POS, ulCurPos1);
gc1REG(HW_CURSOR1_ADDR, ulCurAddr1);
}
else
{
gc2REG(HW_CURSOR2_POS, ulCurPos1);
gc2REG(HW_CURSOR2_ADDR, ulCurAddr1);
}
#ifndef USB_MOUSE // USB mouse enabled through MouseEvent ...
if (x != -1)
{
// Enable cursor
//
if (flag == 1)
{
ulTemp = gc1READ(GC1_CONTROL) | HC_ENABLE;
gc1REG(GC1_CONTROL, ulTemp);
}
else
{
ulTemp = gc2READ(GC2_CONTROL) | HC_ENABLE;
gc2REG(GC2_CONTROL, ulTemp);
}
}
#endif // USB_MOUSE
return S_OK;
}
SCODE MQGC::MovePointerSameImage(
int x,
int y)
{
ULONG ulGC1Delta, ulGC2Delta;
ULONG ulCurPos1, ulCurAddr1;
ULONG ulCurPos2, ulCurAddr2;
ULONG ulTemp;
// Adjust for both GCs
UpdateCursorVP(x,y,3);
if (x == -1)
{
// Disable both cursor anyhow
//
ulTemp = gc1READ(GC1_CONTROL) & HC_DISABLE;
gc1REG(GC1_CONTROL, ulTemp);
ulTemp = gc2READ(GC2_CONTROL) & HC_DISABLE;
gc2REG(GC2_CONTROL, ulTemp);
}
// Adjust cursor position
int x1 = x - CursorData.usGC1VPL;
int y1 = y - CursorData.usGC1VPT;
int x2 = x - CursorData.usGC2VPL;
int y2 = y - CursorData.usGC2VPT;
// Panning for GC1
ulGC1Delta = CursorData.usGC1VPT * m_ulScreenStride +
CursorData.usGC1VPL * m_nBytesPerPixel;
gc1REG(IW1_START_ADDR, m_nIW1StartAddr + ulGC1Delta);
// Panning for GC2
ulGC2Delta = CursorData.usGC2VPT * m_ulScreenStride +
CursorData.usGC2VPL * m_nBytesPerPixel;
gc2REG(IW2_START_ADDR, m_nIW2StartAddr + ulGC2Delta);
int newx1 = x1 - m_nXHot; // Hot spot is currently 32,32
int newy1 = y1 - m_nYHot;
int dx1 = 0;
int dy1 = 0;
if( newx1 < 0 )
{
dx1 = -newx1;
newx1 = 0;
}
if( newy1 < 0 )
{
dy1 = -newy1;
newy1 = 0;
}
// Set up cursor position and offset variables
//
#ifdef VC_OFFSET_BUG
if (dy1 == 63)
dy1--;
#endif
ulCurPos1 = ((ULONG)newy1 << 16) | newx1;
ulCurAddr1 = ((ULONG)dy1 << 24) | ((ULONG)dx1 << 16) | m_nCursorStart;
gc1REG(HW_CURSOR1_POS, ulCurPos1);
gc1REG(HW_CURSOR1_ADDR, ulCurAddr1);
int newx2 = x2 - m_nXHot; // Hot spot is currently 32,32
int newy2 = y2 - m_nYHot;
int dx2 = 0;
int dy2 = 0;
if( newx2 < 0 )
{
dx2 = -newx2;
newx2 = 0;
}
if( newy2 < 0 )
{
dy2 = -newy2;
newy2 = 0;
}
// Set up cursor position and offset variables
//
#ifdef VC_OFFSET_BUG
if (dy2 == 63)
dy2--;
#endif
ulCurPos2 = ((ULONG)newy2 << 16) | newx2;
ulCurAddr2 = ((ULONG)dy2 << 24) | ((ULONG)dx2 << 16) | m_nCursorStart;
gc2REG(HW_CURSOR2_POS, ulCurPos2);
gc2REG(HW_CURSOR2_ADDR, ulCurAddr2);
#ifndef USB_MOUSE // USB mouse enabled through MouseEvent ...
if (x != -1)
{
// Enable cursor for both
//
ulTemp = gc1READ(GC1_CONTROL) | HC_ENABLE;
gc1REG(GC1_CONTROL, ulTemp);
ulTemp = gc2READ(GC2_CONTROL) | HC_ENABLE;
gc2REG(GC2_CONTROL, ulTemp);
}
#endif // USB_MOUSE
return S_OK;
}
#ifdef SUPPORT_LARGE_DESKTOP
SCODE MQGC::MovePointerLD(
int x,
int y )
{
int flag1x,flag2x,flag1y,flag2y;
ULONG ulGC1Delta, ulGC2Delta;
ULONG ulCurPos1, ulCurAddr1;
ULONG ulCurPos2, ulCurAddr2;
ULONG ulTemp;
int x1,y1,x2,y2;
int dx1 = 0;
int dy1 = 0;
int dx2 = 0;
int dy2 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -