📄 sdl_os2fslib.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2004 Sam Lantinga 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 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org*/#include "SDL_config.h"#define _ULS_CALLCONV_#define CALLCONV _System#include <unidef.h> // Unicode API#include <uconv.h> // Unicode API (codepage conversion)#include <process.h>#include <time.h>#include "SDL_video.h"#include "SDL_mouse.h"#include "../SDL_sysvideo.h"#include "../SDL_pixels_c.h"#include "../../events/SDL_events_c.h"#include "SDL_os2fslib.h"static ULONG ulFCFToUse = FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON | FCF_MAXBUTTON | FCF_NOBYTEALIGN | FCF_SIZEBORDER | FCF_TASKLIST;static int bMouseCaptured = 0;static int bMouseCapturable = 0;static HPOINTER hptrGlobalPointer = NULL;static HPOINTER hptrCurrentIcon = NULL;static int iWindowSizeX = 320;static int iWindowSizeY = 200;static int bWindowResized = 0;#pragma pack(1)typedef struct BMPINFO{ BITMAPINFO; RGB clr;} BMPINFO, *PBMPINFO;#pragma pack()// Backdoors:DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF){ ulFCFToUse = ulFCF;}// Configuration defines:// We have to report empty alpha mask, otherwise SDL will select// alpha blitters, and this will have unwanted results, as we don't// support alpha channel in FSLib yet.#define REPORT_EMPTY_ALPHA_MASK// Experimental: Move every FSLib_BitBlt() call into window message// processing function.// This may fix dirt left on desktop. Or not.//#define BITBLT_IN_WINMESSAGEPROC// Experimental-2: Use WinLockWindowUpdate() in around bitblts!// This is not enabled, because it seems to cause more problems// than good.//#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS// Use the following to show resized image instead of black stuff// even if the surface is resizable.//#define RESIZE_EVEN_IF_RESIZABLE/* The translation table from a VK keysym to a SDL keysym */static SDLKey HWScanKeyMap[256];static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed);static int iShiftIsPressed;#ifdef BITBLT_IN_WINMESSAGEPROC#define WM_UPDATERECTSREQUEST WM_USER+50#endif#ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ { \ WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \ FSLib_BitBlt(hwnd, buffer, top, left, width, height); \ WinLockWindowUpdate(HWND_DESKTOP, NULL); \ }#else#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ FSLib_BitBlt(hwnd, buffer, top, left, width, height);#endif///////////////////////////////////////////////////////////////////////// SetAccessableWindowPos//// Same as WinSetWindowPos(), but takes care for the window to be// always on the screen, the titlebar will be accessable everytime.///////////////////////////////////////////////////////////////////////static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind, LONG x, LONG y, LONG cx, LONG cy, ULONG fl){ SWP swpDesktop, swp; // Get desktop area WinQueryWindowPos(HWND_DESKTOP, &swpDesktop); if ((fl & SWP_MOVE) && (fl & SWP_SIZE)) { // If both moving and sizing, then change size and pos now!! if (x+cx>swpDesktop.cx) x = swpDesktop.cx - cx; if (x<0) x = 0; if (y<0) y = 0; if (y+cy>swpDesktop.cy) y = swpDesktop.cy - cy; return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); } else if (fl & SWP_MOVE) { // Just moving WinQueryWindowPos(hwnd, &swp); if (x+swp.cx>swpDesktop.cx) x = swpDesktop.cx - swp.cx; if (x<0) x = 0; if (y<0) y = 0; if (y+swp.cy>swpDesktop.cy) y = swpDesktop.cy - swp.cy; return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); } else if (fl & SWP_SIZE) { // Just sizing WinQueryWindowPos(hwnd, &swp); x = swp.x; y = swp.y; if (x+cx>swpDesktop.cx) x = swpDesktop.cx - cx; if (x<0) x = 0; if (y<0) y = 0; if (y+cy>swpDesktop.cy) y = swpDesktop.cy - cy; return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE); } else return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);}static UniChar NativeCharToUniChar(int chcode){ UniChar ucResult = (UniChar) chcode; int rc; UconvObject ucoTemp; char achFrom[2]; char *pchFrom; size_t iFromCount; UniChar aucTo[10]; UniChar *pucTo; size_t iToCount; size_t iNonIdentical; // Create unicode convert object rc = UniCreateUconvObject(L"", &ucoTemp); if (rc!=ULS_SUCCESS) { // Could not create convert object! return ucResult; } // Convert language code string to unicode string achFrom[0] = (char) chcode; achFrom[1] = 0; iFromCount = sizeof(char) * 2; iToCount = sizeof(UniChar) * 2; pucTo = &(aucTo[0]); pchFrom = &(achFrom[0]); rc = UniUconvToUcs(ucoTemp, &pchFrom, &iFromCount, &pucTo, &iToCount, &iNonIdentical); if (rc!=ULS_SUCCESS) { // Could not convert language code to UCS string! UniFreeUconvObject(ucoTemp); return ucResult; } UniFreeUconvObject(ucoTemp);#ifdef DEBUG_BUILD printf("%02x converted to %02x\n", (int) chcode, (int) (aucTo[0]));#endif return aucTo[0];}///////////////////////////////////////////////////////////////////////// TranslateKey//// This creates SDL Keycodes from VK_ and hardware scan codes///////////////////////////////////////////////////////////////////////static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed){ keysym->scancode = (unsigned char) scancode; keysym->mod = KMOD_NONE; keysym->unicode = 0; if (iPressed && SDL_TranslateUNICODE) { if (chcode) keysym->unicode = NativeCharToUniChar(chcode); else keysym->unicode = vkey; } keysym->sym = HWScanKeyMap[scancode]; // Now stuffs based on state of shift key(s)! if (vkey == VK_SHIFT) { iShiftIsPressed = iPressed; } if ((iShiftIsPressed) && (SDL_TranslateUNICODE)) { // Change syms, if Unicode stuff is required // I think it's silly, but it's SDL... switch (keysym->sym) { case SDLK_BACKQUOTE: keysym->sym = '~'; break; case SDLK_1: keysym->sym = SDLK_EXCLAIM; break; case SDLK_2: keysym->sym = SDLK_AT; break; case SDLK_3: keysym->sym = SDLK_HASH; break; case SDLK_4: keysym->sym = SDLK_DOLLAR; break; case SDLK_5: keysym->sym = '%'; break; case SDLK_6: keysym->sym = SDLK_CARET; break; case SDLK_7: keysym->sym = SDLK_AMPERSAND; break; case SDLK_8: keysym->sym = SDLK_ASTERISK; break; case SDLK_9: keysym->sym = SDLK_LEFTPAREN; break; case SDLK_0: keysym->sym = SDLK_RIGHTPAREN; break; case SDLK_MINUS: keysym->sym = SDLK_UNDERSCORE; break; case SDLK_PLUS: keysym->sym = SDLK_EQUALS; break; case SDLK_LEFTBRACKET: keysym->sym = '{'; break; case SDLK_RIGHTBRACKET: keysym->sym = '}'; break; case SDLK_SEMICOLON: keysym->sym = SDLK_COLON; break; case SDLK_QUOTE: keysym->sym = SDLK_QUOTEDBL; break; case SDLK_BACKSLASH: keysym->sym = '|'; break; case SDLK_COMMA: keysym->sym = SDLK_LESS; break; case SDLK_PERIOD: keysym->sym = SDLK_GREATER; break; case SDLK_SLASH: keysym->sym = SDLK_QUESTION; break; default: break; } } return keysym;}#define CONVERTMOUSEPOSITION() \ /* We have to inverse the mouse position, because every non-os/2 system */ \ /* has a coordinate system where the (0;0) is the top-left corner, */ \ /* while on os/2 it's the bottom left corner! */ \ if (FSLib_QueryFSMode(hwnd)) \ { \ /* We're in FS mode! */ \ /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \ /* big as the source buffer (can be bigger) */ \ /* So, limit mouse pos to source buffer size! */ \ if (ppts->x<0) ppts->x = 0; \ if (ppts->y<0) ppts->y = 0; \ if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \ if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \ pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \ ptl.x = ppts->x; ptl.y = ppts->y; \ WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \ WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \ /* Then convert OS/2 position to SDL position */ \ ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \ } else \ { \ SWP swpClient; \ /* We're in windowed mode! */ \ WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \ /* Convert OS/2 mouse position to SDL position, and also scale it! */ \ (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \ (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \ (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \ }///////////////////////////////////////////////////////////////////////// WndProc//// This is the message processing window procedure for the// SDLWindowClass, which is the client window in our application.// It handles switching back and away from the app (taking care of// going out and back to and from fullscreen mode), sending keystrokes// and mouse events to where it has to be sent, etc...///////////////////////////////////////////////////////////////////////static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){ HPS ps; RECTL rcl; SDL_VideoDevice *pVideo = NULL; switch (msg) { case WM_CHAR: // Keypress notification#ifdef DEBUG_BUILD// printf("WM_CHAR\n"); fflush(stdout);#endif pVideo = WinQueryWindowPtr(hwnd, 0); if (pVideo) { /* // We skip repeated keys: if (CHARMSG(&msg)->cRepeat>1) {#ifdef DEBUG_BUILD// printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout);#endif return (MRESULT) TRUE; } */ // If it's not repeated, then let's see if its pressed or released! if (SHORT1FROMMP(mp1) & KC_KEYUP) { // A key has been released SDL_keysym keysym;#ifdef DEBUG_BUILD// printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code#endif // One problem is with F1, which gets only the keyup message because // it is a system key. // So, when we get keyup message, we simulate keydown too! // UPDATE: // This problem should be solved now, that the accelerator keys are // disabled for this window!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -