📄 cursor.c
字号:
/*
** $Id: cursor.c,v 1.55 2004/04/16 08:39:36 weiym Exp $
**
** cursor.c: the Cursor Support module of MiniGUI.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 1999 ~ 2002 Wei Yongming.
**
** Current maintainer: Wei Yongming.
**
** Create date: 1999.01.06
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#include "gal.h"
#include "dc.h"
#include "memops.h"
#include "inline.h"
#include "gal.h"
#include "cursor.h"
#include "ial.h"
#include "readbmp.h"
#include "misc.h"
#include "cursor.h"
#include "sysres.h"
// mutex ensuring exclusive access to mouse.
pthread_mutex_t __mg_mouselock;
static int curx, cury;
static int oldx = -1, oldy;
static RECT cliprc = { 0, 0, 0, 0};
#ifdef _CURSOR_SUPPORT
static PCURSOR SysCursor [MAX_SYSCURSORINDEX + 1];
static HCURSOR def_cursor;
static BYTE* savedbits = NULL;
static BYTE* cursorbits = NULL;
static int csrimgsize;
static int csrimgpitch;
static int oldboxleft = -100, oldboxtop = -100;
static int nShowCount = 0;
static PCURSOR pCurCsr = NULL;
#ifdef _USE_NEWGAL
Uint8* GetPixelUnderCursor (int x, int y, gal_pixel* pixel)
{
Uint8* dst = NULL;
pthread_mutex_lock (&__mg_mouselock);
if (nShowCount >= 0 && pCurCsr
&& x >= oldboxleft && y >= oldboxtop
&& (x < oldboxleft + CURSORWIDTH)
&& (y < oldboxtop + CURSORHEIGHT)) {
int _x = x - oldboxleft;
int _y = y - oldboxtop;
dst = savedbits + _y * csrimgpitch
+ _x * __gal_screen->format->BytesPerPixel;
*pixel = _mem_get_pixel (dst, __gal_screen->format->BytesPerPixel);
}
pthread_mutex_unlock (&__mg_mouselock);
return dst;
}
#endif
// Cursor creating and destroying.
// Only called from InitCursor and client code.
HCURSOR GUIAPI LoadCursorFromFile(const char* filename)
{
FILE* fp;
WORD wTemp;
int w, h, xhot, yhot, colornum;
DWORD size, offset;
DWORD imagesize, imagew, imageh;
BYTE* image;
HCURSOR csr = 0;
if( !(fp = fopen(filename, "rb")) ) return 0;
fseek(fp, sizeof(WORD), SEEK_SET);
// the cbType of struct CURSORDIR.
wTemp = MGUI_ReadLE16FP (fp);
if(wTemp != 2) goto error;
// skip the cdCount of struct CURSORDIR, we always use the first cursor.
fseek(fp, sizeof(WORD), SEEK_CUR);
// cursor info, read the members of struct CURSORDIRENTRY.
w = fgetc (fp); // the width of first cursor.
h = fgetc (fp); // the height of first cursor.
if(w != CURSORWIDTH || h != CURSORHEIGHT) goto error;
fseek(fp, sizeof(BYTE)*2, SEEK_CUR); // skip the bColorCount and bReserved.
wTemp = MGUI_ReadLE16FP (fp);
xhot = wTemp;
wTemp = MGUI_ReadLE16FP (fp);
yhot = wTemp;
size = MGUI_ReadLE32FP (fp);
offset = MGUI_ReadLE32FP (fp);
// read the cursor image info.
fseek(fp, offset, SEEK_SET);
fseek(fp, sizeof(DWORD), SEEK_CUR); // skip the biSize member.
imagew = MGUI_ReadLE32FP (fp);
imageh = MGUI_ReadLE32FP (fp);
// check the biPlanes member;
wTemp = MGUI_ReadLE16FP (fp);
if(wTemp != 1) goto error;
// check the biBitCount member;
wTemp = MGUI_ReadLE16FP (fp);
if(wTemp > 4) goto error;
colornum = (int)wTemp;
fseek(fp, sizeof(DWORD), SEEK_CUR); // skip the biCompression members.
imagesize = MGUI_ReadLE32FP (fp);
// skip the rest members and the color table.
fseek(fp, sizeof(DWORD)*4 + sizeof(BYTE)*(4<<colornum), SEEK_CUR);
// allocate memory for image.
if ((image = (BYTE*)ALLOCATE_LOCAL (imagesize)) == NULL)
goto error;
// read image
fread (image, imagesize, 1, fp);
csr = CreateCursor(xhot, yhot, w, h,
image + (imagesize - MONOSIZE), image, colornum);
DEALLOCATE_LOCAL (image);
error:
fclose (fp);
return csr;
}
HCURSOR GUIAPI LoadCursorFromMem (const void* area)
{
const Uint8* p = (Uint8*)area;
WORD wTemp;
int w, h, xhot, yhot, colornum;
DWORD size, offset;
DWORD imagesize, imagew, imageh;
p += sizeof (WORD);
wTemp = MGUI_ReadLE16Mem (&p);
if(wTemp != 2) goto error;
// skip the cdCount of struct CURSORDIR, we always use the first cursor.
p += sizeof (WORD);
// cursor info, read the members of struct CURSORDIRENTRY.
w = *p++; // the width of first cursor.
h = *p++; // the height of first cursor.
if (w != CURSORWIDTH || h != CURSORHEIGHT)
goto error;
// skip the bColorCount and bReserved.
p += sizeof(BYTE)*2;
xhot = MGUI_ReadLE16Mem (&p);
yhot = MGUI_ReadLE16Mem (&p);
size = MGUI_ReadLE32Mem (&p);
offset = MGUI_ReadLE32Mem (&p);
// read the cursor image info.
p = (Uint8*)area + offset;
// skip the biSize member.
p += sizeof (DWORD);
imagew = MGUI_ReadLE32Mem (&p);
imageh = MGUI_ReadLE32Mem (&p);
// check the biPlanes member;
wTemp = MGUI_ReadLE16Mem (&p);
if (wTemp != 1) goto error;
// check the biBitCount member;
wTemp = MGUI_ReadLE16Mem (&p);
if (wTemp > 4) goto error;
colornum = wTemp;
// skip the biCompression members.
p += sizeof (DWORD);
imagesize = MGUI_ReadLE32Mem (&p);
// skip the rest members and the color table.
p += sizeof(DWORD)*4 + sizeof(BYTE)*(4<<colornum);
return CreateCursor (xhot, yhot, w, h,
p + (imagesize - MONOSIZE), p, colornum);
error:
return 0;
}
#ifdef _USE_NEWGAL
static BITMAP csr_bmp = {BMP_TYPE_NORMAL, 0, 0, 0, 0, CURSORWIDTH, CURSORHEIGHT};
#endif
// Only called from InitCursor and client code.
HCURSOR GUIAPI CreateCursor(int xhotspot, int yhotspot, int w, int h,
const BYTE* pANDBits, const BYTE* pXORBits, int colornum)
{
PCURSOR pcsr;
if( w != CURSORWIDTH || h != CURSORHEIGHT ) return 0;
// allocate memory.
if( !(pcsr = (PCURSOR)malloc(sizeof(CURSOR))) ) return 0;
if( !(pcsr->AndBits = malloc(csrimgsize)) ) {
free(pcsr);
return 0;
}
if( !(pcsr->XorBits = malloc(csrimgsize)) ) {
free(pcsr->AndBits);
free(pcsr);
return 0;
}
pcsr->xhotspot = xhotspot;
pcsr->yhotspot = yhotspot;
pcsr->width = w;
pcsr->height = h;
#ifdef _USE_NEWGAL
if (colornum == 1) {
ExpandMonoBitmap (HDC_SCREEN, pcsr->AndBits, csrimgpitch, pANDBits, MONOPITCH,
w, h, MYBMP_FLOW_UP, 0, 0xFFFFFFFF);
ExpandMonoBitmap (HDC_SCREEN, pcsr->XorBits, csrimgpitch, pXORBits, MONOPITCH,
w, h, MYBMP_FLOW_UP, 0, 0xFFFFFFFF);
}
else if (colornum == 4) {
ExpandMonoBitmap (HDC_SCREEN, pcsr->AndBits, csrimgpitch, pANDBits, MONOPITCH,
w, h, MYBMP_FLOW_UP, 0, 0xFFFFFFFF);
Expand16CBitmap (HDC_SCREEN, pcsr->XorBits, csrimgpitch, pXORBits, MONOPITCH*4,
w, h, MYBMP_FLOW_UP, NULL);
}
#else
if(colornum == 1) {
ExpandMonoBitmap (HDC_SCREEN, w, h, pANDBits, MONOPITCH, MYBMP_FLOW_UP,
pcsr->AndBits, csrimgpitch, 0, 0xFFFFFFFF);
ExpandMonoBitmap (HDC_SCREEN, w, h, pXORBits, MONOPITCH, MYBMP_FLOW_UP,
pcsr->XorBits, csrimgpitch, 0, 0xFFFFFFFF);
}
else if(colornum == 4) {
ExpandMonoBitmap (HDC_SCREEN, w, h, pANDBits, MONOPITCH, MYBMP_FLOW_UP,
pcsr->AndBits, csrimgpitch, 0, 0xFFFFFFFF);
Expand16CBitmap (HDC_SCREEN, w, h, pXORBits, MONOPITCH*4, MYBMP_FLOW_UP,
pcsr->XorBits, csrimgpitch, NULL);
}
#endif
return (HCURSOR)pcsr;
}
// Only called from client code.
BOOL GUIAPI DestroyCursor(HCURSOR hcsr)
{
int i;
PCURSOR pcsr = (PCURSOR)hcsr;
if (pcsr == NULL)
return TRUE;
for(i = 0; i <= MAX_SYSCURSORINDEX; i++)
{
if(pcsr == SysCursor[i])
return FALSE;
}
free(pcsr->AndBits);
free(pcsr->XorBits);
free(pcsr);
return TRUE;
}
// Only called from client code, and accessed items are not changable ones.
HCURSOR GUIAPI GetSystemCursor(int csrid)
{
if(csrid > MAX_SYSCURSORINDEX || csrid < 0)
return 0;
return (HCURSOR)(SysCursor[csrid]);
}
HCURSOR GUIAPI GetDefaultCursor (void)
{
return def_cursor;
}
#define CURSORSECTION "cursorinfo"
BOOL InitCursor(void)
{
char szValue[MAX_NAME + 1];
int number;
int i;
#ifdef _USE_NEWGAL
csrimgsize = GAL_GetBoxSize (__gal_screen, CURSORWIDTH, CURSORHEIGHT, &csrimgpitch);
csr_bmp.bmBitsPerPixel = __gal_screen->format->BitsPerPixel;
csr_bmp.bmBytesPerPixel = __gal_screen->format->BytesPerPixel;
csr_bmp.bmPitch = csrimgpitch;
#else
csrimgpitch = CURSORWIDTH * BYTESPERPHYPIXEL;
csrimgsize = csrimgpitch * CURSORHEIGHT;
#endif
if( !(savedbits = malloc(csrimgsize)) )
return FALSE;
if( !(cursorbits = malloc(csrimgsize)) )
{
free(savedbits);
savedbits = NULL;
return FALSE;
}
if( GetMgEtcValue (CURSORSECTION, "cursornumber", szValue, 10) < 0 )
goto error;
number = atoi(szValue);
if(number <= 0)
return TRUE;
number = number < (MAX_SYSCURSORINDEX + 1) ?
number : (MAX_SYSCURSORINDEX + 1);
for(i = 0; i < number; i++) {
if ( !(SysCursor[i] = LoadSystemCursor(i)) )
goto error;
}
pthread_mutex_init(&__mg_mouselock, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -