📄 cursor.c
字号:
// cursor.c: the Cursor Support module of MiniGUI.//// Copyright (C) 1999, Wei Yongming.//// Current maintainer: Wei Yongming./*** This library is free software; you can redistribute it and/or** modify it under the terms of the GNU Library General Public** License as published by the Free Software Foundation; either** version 2 of the License, or (at your option) any later version.**** This library 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** Library General Public License for more details.**** You should have received a copy of the GNU Library General Public** License along with this library; if not, write to the Free** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,** MA 02111-1307, USA*/// Create date: 1999.01.06// Last modified date: 1999.01.06//// Modify records://// Who When Where For What Status//-----------------------------------------------------------------------------// WEI Yongming 1999/10/27 Tsinghua Fix SetCursorPos bug Working//// TODO:// #include <stdio.h>#include <stddef.h>#include <stdlib.h>#ifndef __ECOS# include <malloc.h>#endif#include <string.h>#include <pthread.h>#include <errno.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "gal.h"#include "cursor.h"#include "ial.h"#define __NO_MOUSE 0#define CURSORWIDTH 32#define CURSORHEIGHT 32#define MONOSIZE (CURSORWIDTH*CURSORHEIGHT/8)#define MONOPITCH 4#define CURSORSECTION "cursorinfo"#ifndef lintstatic char fileid[] = "$Id: cursor.c,v 1.11 2000/11/10 05:53:52 ymwei Exp $";#endifextern pthread_mutex_t gdilock;// mutex ensuring exclusive access to mouse.pthread_mutex_t mouselock; static PCURSOR SysCursor [MAX_SYSCURSORINDEX + 1];static HCURSOR def_cursor;static BYTE* savedbits = NULL;static BYTE* cursorbits = NULL;static int csrimgsize; static int nShowCount = 0;static PCURSOR pCurCsr = NULL;// Cursor creating and destroying.// Only called from InitCursor and client code.HCURSOR GUIAPI LoadCursorFromFile(const char* filename){ FILE* fp; WORD wTemp; BYTE bTemp; int w, h, xhot, yhot, colornum; DWORD size, offset; DWORD imagesize, imagew, imageh; BYTE* image; if( !(fp = fopen(filename, "rb")) ) return 0; fseek(fp, sizeof(WORD), SEEK_SET); // the cbType of struct CURSORDIR. fread(&wTemp, sizeof(WORD), 1, 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. fread(&bTemp, sizeof(BYTE), 1, fp); w = bTemp; // the width of first cursor. fread(&bTemp, sizeof(BYTE), 1, fp); h = bTemp; // the height of first cursor. if(w != CURSORWIDTH || h != CURSORHEIGHT) goto error; fseek(fp, sizeof(BYTE)*2, SEEK_CUR); // skip the bColorCount and bReserved. fread(&wTemp, sizeof(WORD), 1, fp); xhot = wTemp; fread(&wTemp, sizeof(WORD), 1, fp); yhot = wTemp; fread(&size, sizeof(DWORD), 1, fp); fread(&offset, sizeof(DWORD), 1, fp); // read the cursor image info. fseek(fp, offset, SEEK_SET); fseek(fp, sizeof(DWORD), SEEK_CUR); // skip the biSize member. fread(&imagew, sizeof(DWORD), 1, fp); fread(&imageh, sizeof(DWORD), 1, fp); // check the biPlanes member; fread(&wTemp, sizeof(WORD), 1, fp); if(wTemp != 1) goto error; // check the biBitCount member; fread(&wTemp, sizeof(WORD), 1, fp); if(wTemp > 4) goto error; colornum = (int)wTemp; fseek(fp, sizeof(DWORD), SEEK_CUR); // skip the biCompression members. fread(&imagesize, sizeof(DWORD), 1, fp); // skip the rest members and the color table. fseek(fp, sizeof(DWORD)*4 + sizeof(BYTE)*(4<<colornum), SEEK_CUR); // allocate memory for image. image = (BYTE*)alloca(imagesize); // read image fread(image, imagesize, 1, fp); fclose(fp); return CreateCursor(xhot, yhot, w, h, image + (imagesize - MONOSIZE), image, colornum);error: fclose(fp); return 0;}// 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; if(colornum == 1) { ExpandMonoBitmap (HDC_SCREEN, w, h, pANDBits, BMP_FLOW_UP, MONOPITCH, pcsr->AndBits, 0xFFFFFFFF, 0); ExpandMonoBitmap (HDC_SCREEN, w, h, pXORBits, BMP_FLOW_UP, MONOPITCH, pcsr->XorBits, 0xFFFFFFFF, 0); } else if(colornum == 4) { ExpandMonoBitmap (HDC_SCREEN, w, h, pANDBits, BMP_FLOW_UP, MONOPITCH, pcsr->AndBits, 0xFFFFFFFF, 0); Expand16CBitmap (HDC_SCREEN, w, h, pXORBits, BMP_FLOW_UP, MONOPITCH*4, pcsr->XorBits, NULL); } 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;}// Must be called at startup.BOOL InitCursor( void ){ char szPathName[MAX_PATH + 1]; char szFileName[MAX_PATH + 1]; char szKey[10]; char szValue[MAX_FILENAME + 1]; int number; int i; csrimgsize = CURSORWIDTH * CURSORHEIGHT * BYTESPERPHYPIXEL; if( !(savedbits = malloc(csrimgsize)) ) return FALSE; if( !(cursorbits = malloc(csrimgsize)) ) { free(savedbits); savedbits = NULL; return FALSE; } if( GetValueFromEtcFile(ETCFILEPATH, CURSORSECTION, "cursorpath", szPathName, MAX_PATH) < 0 ) goto error; if( GetValueFromEtcFile(ETCFILEPATH, CURSORSECTION, "cursornumber", szValue, 10) < 0 ) goto error; number = atoi(szValue); if(number <= 0)#if __NO_MOUSE goto error;#else return TRUE;#endif number = number < (MAX_SYSCURSORINDEX + 1) ? number : (MAX_SYSCURSORINDEX + 1); for(i = 0; i < number; i++) { sprintf(szKey, "cursor%d", i); if( GetValueFromEtcFile(ETCFILEPATH, CURSORSECTION, szKey, szValue, MAX_FILENAME) < 0 ) goto error; strcpy(szFileName, szPathName); strcat(szFileName, szValue); if( !(SysCursor[i] = (PCURSOR)LoadCursorFromFile(szFileName)) ) goto error; } pthread_mutex_init(&mouselock, NULL); return TRUE;error: TerminateCursor(); return FALSE;}// The following function must be called at last. BOOL TerminateCursor( void ){ int i; if( !savedbits ) return FALSE; free(savedbits); free(cursorbits); savedbits = NULL; pCurCsr = NULL; nShowCount = 0; for(i = 0; i<= MAX_SYSCURSORINDEX; i++) { if( SysCursor[i] ) { free(SysCursor[i]->AndBits); free(SysCursor[i]->XorBits); free(SysCursor[i]); SysCursor[i] = NULL; } } return TRUE;}HCURSOR GUIAPI GetCurrentCursor(void){ HCURSOR hcsr; pthread_mutex_lock (&mouselock); hcsr = (HCURSOR)pCurCsr; pthread_mutex_unlock(&mouselock); return hcsr;}static int curx, cury;static int oldx = -1, oldy;static int oldboxleft = -100, oldboxtop = -100;static RECT cliprc = { 0, 0, 0, 0};// Cursor pointer shape and hiding and showing.static inline int boxleft(void){ if(!pCurCsr) return -100; return curx - pCurCsr->xhotspot;}static inline int boxtop(void){ if(!pCurCsr) return -100; return cury - pCurCsr->yhotspot;}static inline void hidecursor(void){ GAL_SetGC(PHYSICALGC); GAL_EnableClipping(PHYSICALGC); GAL_PutBox(PHYSICALGC, oldboxleft, oldboxtop, CURSORWIDTH, CURSORHEIGHT, savedbits);}static inline void showcursor(void){ BYTE* andbits; BYTE* xorbits; int i; int x, y; GAL_SetGC(PHYSICALGC); x = boxleft(); y = boxtop(); GAL_DisableClipping(PHYSICALGC); GAL_GetBox(PHYSICALGC, x, y, CURSORWIDTH, CURSORHEIGHT, savedbits); oldboxleft = x; oldboxtop = y; memcpy(cursorbits, savedbits, csrimgsize); andbits = pCurCsr->AndBits; xorbits = pCurCsr->XorBits; for(i = 0; i < csrimgsize; i++) { cursorbits[i] &= *andbits++; cursorbits[i] ^= *xorbits++; } GAL_EnableClipping(PHYSICALGC); GAL_PutBox(PHYSICALGC, x, y, CURSORWIDTH, CURSORHEIGHT, cursorbits);}// The return value indicates whether mouse has moved. // TRUE for moved.BOOL GUIAPI RefreshCursor(int* x, int* y, int* button){ pthread_mutex_lock (&gdilock); pthread_mutex_lock (&mouselock); IAL_UpdateMouse (); *x = curx = IAL_GetMouseX (); *y = cury = IAL_GetMouseY (); *button = IAL_GetMouseButton (); if(oldx != curx || oldy != cury) { if(nShowCount >= 0 && pCurCsr) { hidecursor(); showcursor(); } oldx = curx; oldy = cury; pthread_mutex_unlock(&mouselock); pthread_mutex_unlock(&gdilock); return TRUE; } pthread_mutex_unlock(&mouselock); pthread_mutex_unlock(&gdilock); return FALSE;}// Cursor clipping support.void GUIAPI ClipCursor(const RECT* prc){ RECT rc; pthread_mutex_lock (&mouselock); if( IsRectEmpty(&cliprc) ) SetRect(&cliprc, 0, 0, WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); if(prc == NULL) { IAL_SetMouseRange (0,0,WIDTHOFPHYGC - 1,HEIGHTOFPHYGC - 1); SetRect(&cliprc, 0, 0, WIDTHOFPHYGC - 1, HEIGHTOFPHYGC - 1); pthread_mutex_unlock(&mouselock); return; } memcpy(&rc, prc, sizeof(RECT)); NormalizeRect(&rc); IntersectRect(&cliprc, &rc, &cliprc); NormalizeRect(&cliprc); IAL_SetMouseRange (cliprc.left,cliprc.top, cliprc.right,cliprc.bottom); pthread_mutex_unlock(&mouselock);}void GUIAPI GetClipCursor(RECT* prc){ pthread_mutex_lock (&mouselock); memcpy(prc, &cliprc, sizeof(RECT)); pthread_mutex_unlock(&mouselock);}HCURSOR GUIAPI SetCursorEx (HCURSOR hcsr, BOOL setdef){ PCURSOR old, pcsr; pthread_mutex_lock (&mouselock); if (setdef) { old = (PCURSOR) def_cursor; def_cursor = hcsr; } else old = pCurCsr; if ((PCURSOR)hcsr == pCurCsr) { pthread_mutex_unlock(&mouselock); return (HCURSOR) old; } pthread_mutex_unlock(&mouselock); pthread_mutex_lock (&gdilock); pthread_mutex_lock (&mouselock); pcsr = (PCURSOR)hcsr; if (pCurCsr) hidecursor(); pCurCsr = pcsr; if (nShowCount >= 0 && pCurCsr) showcursor(); pthread_mutex_unlock(&mouselock); pthread_mutex_unlock(&gdilock); return (HCURSOR) old;}void ShowCursorForGDI(BOOL fShow, const RECT* prc){ int csrleft, csrright, csrtop, csrbottom; int intleft, intright, inttop, intbottom; if (!fShow) pthread_mutex_lock (&mouselock); csrleft = boxleft(); csrright = csrleft + CURSORWIDTH; csrtop = boxtop(); csrbottom = csrtop + CURSORHEIGHT; intleft = (csrleft > prc->left) ? csrleft : prc->left; inttop = (csrtop > prc->top) ? csrtop : prc->top; intright = (csrright < prc->right) ? csrright : prc->right; intbottom = (csrbottom < prc->bottom) ? csrbottom : prc->bottom; if(intleft >= intright || inttop >= intbottom) { if (fShow) pthread_mutex_unlock(&mouselock); return; } if (fShow && nShowCount >= 0 && pCurCsr) { showcursor(); } if (!fShow && nShowCount >= 0 && pCurCsr) { hidecursor(); } if (fShow) pthread_mutex_unlock(&mouselock); return;}int GUIAPI ShowCursor(BOOL fShow){ int count; pthread_mutex_lock (&gdilock); pthread_mutex_lock (&mouselock); if(fShow) { nShowCount++; if(nShowCount == 0 && pCurCsr) showcursor(); } else { nShowCount--; if(nShowCount == -1 && pCurCsr); hidecursor(); } count = nShowCount; pthread_mutex_unlock(&mouselock); pthread_mutex_unlock(&gdilock); return count;}// Cursor position.void GUIAPI GetCursorPos(POINT* ppt){ pthread_mutex_lock (&mouselock); ppt->x = curx; ppt->y = cury; pthread_mutex_unlock(&mouselock);}void GUIAPI SetCursorPos(int x, int y){ pthread_mutex_lock (&gdilock); pthread_mutex_lock (&mouselock); IAL_SetMouseXY (x, y); curx = IAL_GetMouseX (); cury = IAL_GetMouseY (); if(oldx != curx || oldy != cury) { if(nShowCount >= 0 && pCurCsr) { hidecursor(); showcursor(); } oldx = curx; oldy = cury; } pthread_mutex_unlock(&mouselock); pthread_mutex_unlock(&gdilock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -