1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2004 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #define _ULS_CALLCONV_
25 #define CALLCONV _System
26 #include <unidef.h> // Unicode API
27 #include <uconv.h> // Unicode API (codepage conversion)
28
29 #include <process.h>
30 #include <time.h>
31
32 #include "SDL_video.h"
33 #include "SDL_mouse.h"
34 #include "../SDL_sysvideo.h"
35 #include "../SDL_pixels_c.h"
36 #include "../../events/SDL_events_c.h"
37
38 #include "SDL_os2fslib.h"
39
40 static ULONG ulFCFToUse =
41 FCF_TITLEBAR |
42 FCF_SYSMENU |
43 FCF_MINBUTTON |
44 FCF_MAXBUTTON |
45 FCF_NOBYTEALIGN |
46 FCF_SIZEBORDER |
47 FCF_TASKLIST;
48
49 static int bMouseCaptured = 0;
50 static int bMouseCapturable = 0;
51 static HPOINTER hptrGlobalPointer = NULL;
52 static HPOINTER hptrCurrentIcon = NULL;
53 static int iWindowSizeX = 320;
54 static int iWindowSizeY = 200;
55 static int bWindowResized = 0;
56
57 #pragma pack(1)
58 typedef struct BMPINFO
59 {
60 BITMAPINFO;
61 RGB clr;
62 } BMPINFO, *PBMPINFO;
63 #pragma pack()
64
65
66 // Backdoors:
SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF)67 DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF)
68 {
69 ulFCFToUse = ulFCF;
70 }
71
72 // Configuration defines:
73
74 // We have to report empty alpha mask, otherwise SDL will select
75 // alpha blitters, and this will have unwanted results, as we don't
76 // support alpha channel in FSLib yet.
77 #define REPORT_EMPTY_ALPHA_MASK
78
79 // Experimental: Move every FSLib_BitBlt() call into window message
80 // processing function.
81 // This may fix dirt left on desktop. Or not.
82 //#define BITBLT_IN_WINMESSAGEPROC
83
84 // Experimental-2: Use WinLockWindowUpdate() in around bitblts!
85 // This is not enabled, because it seems to cause more problems
86 // than good.
87 //#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
88
89 // Use the following to show resized image instead of black stuff
90 // even if the surface is resizable.
91 //#define RESIZE_EVEN_IF_RESIZABLE
92
93 /* The translation table from a VK keysym to a SDL keysym */
94 static SDLKey HWScanKeyMap[256];
95 static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed);
96 static int iShiftIsPressed;
97
98 #ifdef BITBLT_IN_WINMESSAGEPROC
99 #define WM_UPDATERECTSREQUEST WM_USER+50
100 #endif
101
102 #ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS
103 #define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
104 { \
105 WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \
106 FSLib_BitBlt(hwnd, buffer, top, left, width, height); \
107 WinLockWindowUpdate(HWND_DESKTOP, NULL); \
108 }
109 #else
110 #define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \
111 FSLib_BitBlt(hwnd, buffer, top, left, width, height);
112 #endif
113
114 /////////////////////////////////////////////////////////////////////
115 //
116 // SetAccessableWindowPos
117 //
118 // Same as WinSetWindowPos(), but takes care for the window to be
119 // always on the screen, the titlebar will be accessable everytime.
120 //
121 /////////////////////////////////////////////////////////////////////
SetAccessableWindowPos(HWND hwnd,HWND hwndInsertBehind,LONG x,LONG y,LONG cx,LONG cy,ULONG fl)122 static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind,
123 LONG x, LONG y,
124 LONG cx, LONG cy,
125 ULONG fl)
126 {
127 SWP swpDesktop, swp;
128 // Get desktop area
129 WinQueryWindowPos(HWND_DESKTOP, &swpDesktop);
130
131 if ((fl & SWP_MOVE) && (fl & SWP_SIZE))
132 {
133 // If both moving and sizing, then change size and pos now!!
134 if (x+cx>swpDesktop.cx)
135 x = swpDesktop.cx - cx;
136 if (x<0)
137 x = 0;
138 if (y<0)
139 y = 0;
140 if (y+cy>swpDesktop.cy)
141 y = swpDesktop.cy - cy;
142 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
143 } else
144 if (fl & SWP_MOVE)
145 {
146 // Just moving
147 WinQueryWindowPos(hwnd, &swp);
148 if (x+swp.cx>swpDesktop.cx)
149 x = swpDesktop.cx - swp.cx;
150 if (x<0)
151 x = 0;
152 if (y<0)
153 y = 0;
154 if (y+swp.cy>swpDesktop.cy)
155 y = swpDesktop.cy - swp.cy;
156 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
157 } else
158 if (fl & SWP_SIZE)
159 {
160 // Just sizing
161 WinQueryWindowPos(hwnd, &swp);
162 x = swp.x;
163 y = swp.y;
164 if (x+cx>swpDesktop.cx)
165 x = swpDesktop.cx - cx;
166 if (x<0)
167 x = 0;
168 if (y<0)
169 y = 0;
170 if (y+cy>swpDesktop.cy)
171 y = swpDesktop.cy - cy;
172 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE);
173 } else
174 return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
175 }
176
NativeCharToUniChar(int chcode)177 static UniChar NativeCharToUniChar(int chcode)
178 {
179 UniChar ucResult = (UniChar) chcode;
180 int rc;
181 UconvObject ucoTemp;
182 char achFrom[2];
183 char *pchFrom;
184 size_t iFromCount;
185 UniChar aucTo[10];
186 UniChar *pucTo;
187 size_t iToCount;
188 size_t iNonIdentical;
189
190 // Create unicode convert object
191 rc = UniCreateUconvObject(L"", &ucoTemp);
192 if (rc!=ULS_SUCCESS)
193 {
194 // Could not create convert object!
195 return ucResult;
196 }
197
198 // Convert language code string to unicode string
199 achFrom[0] = (char) chcode;
200 achFrom[1] = 0;
201 iFromCount = sizeof(char) * 2;
202 iToCount = sizeof(UniChar) * 2;
203 pucTo = &(aucTo[0]);
204 pchFrom = &(achFrom[0]);
205
206 rc = UniUconvToUcs(ucoTemp,
207 &pchFrom,
208 &iFromCount,
209 &pucTo,
210 &iToCount,
211 &iNonIdentical);
212
213 if (rc!=ULS_SUCCESS)
214 {
215 // Could not convert language code to UCS string!
216 UniFreeUconvObject(ucoTemp);
217 return ucResult;
218 }
219
220 UniFreeUconvObject(ucoTemp);
221
222 #ifdef DEBUG_BUILD
223 printf("%02x converted to %02x\n", (int) chcode, (int) (aucTo[0]));
224 #endif
225
226 return aucTo[0];
227 }
228
229 /////////////////////////////////////////////////////////////////////
230 //
231 // TranslateKey
232 //
233 // This creates SDL Keycodes from VK_ and hardware scan codes
234 //
235 /////////////////////////////////////////////////////////////////////
TranslateKey(int vkey,int chcode,int scancode,SDL_keysym * keysym,int iPressed)236 static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed)
237 {
238 keysym->scancode = (unsigned char) scancode;
239 keysym->mod = KMOD_NONE;
240 keysym->unicode = 0;
241
242 if (iPressed && SDL_TranslateUNICODE)
243 {
244 if (chcode)
245 keysym->unicode = NativeCharToUniChar(chcode);
246 else
247 keysym->unicode = vkey;
248 }
249
250 keysym->sym = HWScanKeyMap[scancode];
251
252 // Now stuffs based on state of shift key(s)!
253 if (vkey == VK_SHIFT)
254 {
255 iShiftIsPressed = iPressed;
256 }
257
258 if ((iShiftIsPressed) && (SDL_TranslateUNICODE))
259 {
260 // Change syms, if Unicode stuff is required
261 // I think it's silly, but it's SDL...
262 switch (keysym->sym)
263 {
264 case SDLK_BACKQUOTE:
265 keysym->sym = '~';
266 break;
267 case SDLK_1:
268 keysym->sym = SDLK_EXCLAIM;
269 break;
270 case SDLK_2:
271 keysym->sym = SDLK_AT;
272 break;
273 case SDLK_3:
274 keysym->sym = SDLK_HASH;
275 break;
276 case SDLK_4:
277 keysym->sym = SDLK_DOLLAR;
278 break;
279 case SDLK_5:
280 keysym->sym = '%';
281 break;
282 case SDLK_6:
283 keysym->sym = SDLK_CARET;
284 break;
285 case SDLK_7:
286 keysym->sym = SDLK_AMPERSAND;
287 break;
288 case SDLK_8:
289 keysym->sym = SDLK_ASTERISK;
290 break;
291 case SDLK_9:
292 keysym->sym = SDLK_LEFTPAREN;
293 break;
294 case SDLK_0:
295 keysym->sym = SDLK_RIGHTPAREN;
296 break;
297 case SDLK_MINUS:
298 keysym->sym = SDLK_UNDERSCORE;
299 break;
300 case SDLK_PLUS:
301 keysym->sym = SDLK_EQUALS;
302 break;
303
304 case SDLK_LEFTBRACKET:
305 keysym->sym = '{';
306 break;
307 case SDLK_RIGHTBRACKET:
308 keysym->sym = '}';
309 break;
310
311 case SDLK_SEMICOLON:
312 keysym->sym = SDLK_COLON;
313 break;
314 case SDLK_QUOTE:
315 keysym->sym = SDLK_QUOTEDBL;
316 break;
317 case SDLK_BACKSLASH:
318 keysym->sym = '|';
319 break;
320
321 case SDLK_COMMA:
322 keysym->sym = SDLK_LESS;
323 break;
324 case SDLK_PERIOD:
325 keysym->sym = SDLK_GREATER;
326 break;
327 case SDLK_SLASH:
328 keysym->sym = SDLK_QUESTION;
329 break;
330
331 default:
332 break;
333 }
334 }
335 return keysym;
336 }
337
338 #define CONVERTMOUSEPOSITION() \
339 /* We have to inverse the mouse position, because every non-os/2 system */ \
340 /* has a coordinate system where the (0;0) is the top-left corner, */ \
341 /* while on os/2 it's the bottom left corner! */ \
342 if (FSLib_QueryFSMode(hwnd)) \
343 { \
344 /* We're in FS mode! */ \
345 /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \
346 /* big as the source buffer (can be bigger) */ \
347 /* So, limit mouse pos to source buffer size! */ \
348 if (ppts->x<0) ppts->x = 0; \
349 if (ppts->y<0) ppts->y = 0; \
350 if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \
351 if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \
352 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \
353 ptl.x = ppts->x; ptl.y = ppts->y; \
354 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \
355 WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \
356 /* Then convert OS/2 position to SDL position */ \
357 ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \
358 } else \
359 { \
360 SWP swpClient; \
361 /* We're in windowed mode! */ \
362 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \
363 /* Convert OS/2 mouse position to SDL position, and also scale it! */ \
364 (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \
365 (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \
366 (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \
367 }
368
369
370
371 /////////////////////////////////////////////////////////////////////
372 //
373 // WndProc
374 //
375 // This is the message processing window procedure for the
376 // SDLWindowClass, which is the client window in our application.
377 // It handles switching back and away from the app (taking care of
378 // going out and back to and from fullscreen mode), sending keystrokes
379 // and mouse events to where it has to be sent, etc...
380 //
381 /////////////////////////////////////////////////////////////////////
WndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)382 static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
383 {
384 HPS ps;
385 RECTL rcl;
386 SDL_VideoDevice *pVideo = NULL;
387
388 switch (msg)
389 {
390 case WM_CHAR: // Keypress notification
391 #ifdef DEBUG_BUILD
392 // printf("WM_CHAR\n"); fflush(stdout);
393 #endif
394 pVideo = WinQueryWindowPtr(hwnd, 0);
395 if (pVideo)
396 {
397 /*
398 // We skip repeated keys:
399 if (CHARMSG(&msg)->cRepeat>1)
400 {
401 #ifdef DEBUG_BUILD
402 // printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout);
403 #endif
404 return (MRESULT) TRUE;
405 }
406 */
407
408 // If it's not repeated, then let's see if its pressed or released!
409 if (SHORT1FROMMP(mp1) & KC_KEYUP)
410 {
411 // A key has been released
412 SDL_keysym keysym;
413
414 #ifdef DEBUG_BUILD
415 // printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
416 #endif
417
418 // One problem is with F1, which gets only the keyup message because
419 // it is a system key.
420 // So, when we get keyup message, we simulate keydown too!
421 // UPDATE:
422 // This problem should be solved now, that the accelerator keys are
423 // disabled for this window!
424 /*
425 if (SHORT2FROMMP(mp2)==VK_F1)
426 {
427 SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
428 SHORT1FROMMP(mp2), // Character code
429 CHAR4FROMMP(mp1), // HW Scan code
430 &keysym,0));
431 }*/
432
433 SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
434 SHORT1FROMMP(mp2), // Character code
435 CHAR4FROMMP(mp1), // HW Scan code
436 &keysym,0));
437
438 } else
439 {
440 // A key has been pressed
441 SDL_keysym keysym;
442
443 #ifdef DEBUG_BUILD
444 // printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code
445 #endif
446 // Check for fastkeys: ALT+HOME to toggle FS mode
447 // ALT+END to close app
448 if ((SHORT1FROMMP(mp1) & KC_ALT) &&
449 (SHORT2FROMMP(mp2) == VK_HOME))
450 {
451 #ifdef DEBUG_BUILD
452 printf(" Pressed ALT+HOME!\n"); fflush(stdout);
453 #endif
454 // Only switch between fullscreen and back if it's not
455 // a resizable mode!
456 if (
457 (!pVideo->hidden->pSDLSurface) ||
458 ((pVideo->hidden->pSDLSurface)
459 && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0)
460 )
461 )
462 FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd));
463 #ifdef DEBUG_BUILD
464 else
465 printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout);
466 #endif
467 } else
468 if ((SHORT1FROMMP(mp1) & KC_ALT) &&
469 (SHORT2FROMMP(mp2) == VK_END))
470 {
471 #ifdef DEBUG_BUILD
472 printf(" Pressed ALT+END!\n"); fflush(stdout);
473 #endif
474 // Close window, and get out of loop!
475 // Also send event to SDL application, but we won't
476 // wait for it to be processed!
477 SDL_PrivateQuit();
478 WinPostMsg(hwnd, WM_QUIT, 0, 0);
479 } else
480 {
481
482 SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code
483 SHORT1FROMMP(mp2), // Character code
484 CHAR4FROMMP(mp1), // HW Scan code
485 &keysym,1));
486
487 }
488 }
489 }
490 return (MRESULT) TRUE;
491
492 case WM_TRANSLATEACCEL:
493 {
494 PQMSG pqmsg;
495 pqmsg = (PQMSG) mp1;
496 if (mp1)
497 {
498 if (pqmsg->msg == WM_CHAR)
499 {
500 // WM_CHAR message!
501 // Let's filter the ALT keypress and all other acceleration keys!
502 return (MRESULT) FALSE;
503 }
504 }
505 break; // Default processing (pass to parent until frame control)
506 }
507
508 case WM_PAINT: // Window redraw!
509 #ifdef DEBUG_BUILD
510 printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout);
511 #endif
512 ps = WinBeginPaint(hwnd,0,&rcl);
513 pVideo = FSLib_GetUserParm(hwnd);
514 if (pVideo)
515 {
516 if (!pVideo->hidden->pSDLSurface)
517 {
518 RECTL rclRect;
519 // So, don't blit now!
520 #ifdef DEBUG_BUILD
521 printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout);
522 #endif
523 WinQueryWindowRect(hwnd, &rclRect);
524 // Fill with black
525 WinFillRect(ps, &rclRect, CLR_BLACK);
526 } else
527 {
528 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
529 {
530 int iTop, iLeft, iWidth, iHeight;
531 int iXScaleError, iYScaleError;
532 int iXScaleError2, iYScaleError2;
533 SWP swp;
534
535 // Re-blit the modified area!
536 // For this, we have to calculate the points, scaled!
537 WinQueryWindowPos(hwnd, &swp);
538 #ifdef DEBUG_BUILD
539 printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n",
540 swp.cx,
541 swp.cy,
542 pVideo->hidden->SrcBufferDesc.uiXResolution,
543 pVideo->hidden->SrcBufferDesc.uiYResolution
544 );
545 fflush(stdout);
546 #endif
547
548 #ifndef RESIZE_EVEN_IF_RESIZABLE
549 // But only blit if the window is not resizable, or if
550 // the window is resizable and the source buffer size is the
551 // same as the destination buffer size!
552 if ((!pVideo->hidden->pSDLSurface) ||
553 ((pVideo->hidden->pSDLSurface) &&
554 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
555 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
556 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
557 ) &&
558 (!FSLib_QueryFSMode(hwnd))
559 )
560 )
561 {
562 RECTL rclRect;
563 // Resizable surface and in resizing!
564 // So, don't blit now!
565 #ifdef DEBUG_BUILD
566 printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout);
567 #endif
568 WinQueryWindowRect(hwnd, &rclRect);
569 // Fill with black
570 WinFillRect(ps, &rclRect, CLR_BLACK);
571 } else
572 #endif
573 {
574
575 iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx;
576 iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy;
577 if (iXScaleError<0) iXScaleError = 0;
578 if (iYScaleError<0) iYScaleError = 0;
579 iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution);
580 iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution);
581 if (iXScaleError2<0) iXScaleError2 = 0;
582 if (iYScaleError2<0) iYScaleError2 = 0;
583
584 iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError;
585 iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError;
586 iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1)
587 / swp.cx + 2*iXScaleError;
588 iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1)
589 / swp.cy + 2*iYScaleError;
590
591 iWidth+=iXScaleError2;
592 iHeight+=iYScaleError2;
593
594 if (iTop<0) iTop = 0;
595 if (iLeft<0) iLeft = 0;
596 if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop;
597 if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft;
598
599 #ifdef DEBUG_BUILD
600 printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n",
601 iTop, iLeft, iWidth, iHeight,
602 pVideo->hidden->SrcBufferDesc.uiXResolution,
603 pVideo->hidden->SrcBufferDesc.uiYResolution
604 );
605 fflush(stdout);
606 #endif
607
608 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight);
609 }
610
611 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
612 }
613 }
614 }
615 #ifdef DEBUG_BUILD
616 else
617 {
618 printf("WM_PAINT : No pVideo!\n"); fflush(stdout);
619 }
620 #endif
621 WinEndPaint(ps);
622 #ifdef DEBUG_BUILD
623 printf("WM_PAINT : Done.\n");
624 fflush(stdout);
625 #endif
626 return 0;
627
628 case WM_SIZE:
629 {
630 #ifdef DEBUG_BUILD
631 printf("WM_SIZE : (%d %d)\n",
632 SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout);
633 #endif
634 iWindowSizeX = SHORT1FROMMP(mp2);
635 iWindowSizeY = SHORT2FROMMP(mp2);
636 bWindowResized = 1;
637
638 // Make sure the window will be redrawn
639 WinInvalidateRegion(hwnd, NULL, TRUE);
640 }
641 break;
642
643 case WM_FSLIBNOTIFICATION:
644 #ifdef DEBUG_BUILD
645 printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout);
646 #endif
647 if ((int)mp1 == FSLN_TOGGLEFSMODE)
648 {
649 // FS mode changed, reblit image!
650 pVideo = FSLib_GetUserParm(hwnd);
651 if (pVideo)
652 {
653 if (!pVideo->hidden->pSDLSurface)
654 {
655 // Resizable surface and in resizing!
656 // So, don't blit now!
657 #ifdef DEBUG_BUILD
658 printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout);
659 #endif
660 } else
661 {
662 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR)
663 {
664 if (pVideo->hidden->pSDLSurface)
665 {
666 #ifndef RESIZE_EVEN_IF_RESIZABLE
667 SWP swp;
668
669 // But only blit if the window is not resizable, or if
670 // the window is resizable and the source buffer size is the
671 // same as the destination buffer size!
672 WinQueryWindowPos(hwnd, &swp);
673 if ((!pVideo->hidden->pSDLSurface) ||
674 (
675 (pVideo->hidden->pSDLSurface) &&
676 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
677 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
678 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
679 ) &&
680 (!FSLib_QueryFSMode(hwnd))
681 )
682 )
683 {
684 // Resizable surface and in resizing!
685 // So, don't blit now!
686 #ifdef DEBUG_BUILD
687 printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout);
688 #endif
689 } else
690 #endif
691 {
692 #ifdef DEBUG_BUILD
693 printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout);
694 #endif
695 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
696 0, 0,
697 pVideo->hidden->SrcBufferDesc.uiXResolution,
698 pVideo->hidden->SrcBufferDesc.uiYResolution);
699 }
700 }
701 #ifdef DEBUG_BUILD
702 else
703 printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout);
704 #endif
705
706 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
707 }
708 }
709 }
710 }
711 return (MPARAM) 1;
712
713 case WM_ACTIVATE:
714 #ifdef DEBUG_BUILD
715 printf("WM_ACTIVATE\n"); fflush(stdout);
716 #endif
717
718 pVideo = FSLib_GetUserParm(hwnd);
719 if (pVideo)
720 {
721 pVideo->hidden->fInFocus = (int) mp1;
722 if (pVideo->hidden->fInFocus)
723 {
724 // Went into focus
725 if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
726 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
727 else
728 WinSetPointer(HWND_DESKTOP, NULL);
729
730 if (bMouseCapturable)
731 {
732 // Re-capture the mouse, if we captured it before!
733 WinSetCapture(HWND_DESKTOP, hwnd);
734 bMouseCaptured = 1;
735 {
736 SWP swpClient;
737 POINTL ptl;
738 // Center the mouse to the middle of the window!
739 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
740 ptl.x = 0; ptl.y = 0;
741 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
742 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
743 WinSetPointerPos(HWND_DESKTOP,
744 ptl.x + swpClient.cx/2,
745 ptl.y + swpClient.cy/2);
746 }
747 }
748 } else
749 {
750 // Went out of focus
751 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
752
753 if (bMouseCaptured)
754 {
755 // Release the mouse
756 WinSetCapture(HWND_DESKTOP, hwnd);
757 bMouseCaptured = 0;
758 }
759 }
760 }
761 #ifdef DEBUG_BUILD
762 printf("WM_ACTIVATE done\n"); fflush(stdout);
763 #endif
764
765 break;
766
767 case WM_BUTTON1DOWN:
768 #ifdef DEBUG_BUILD
769 printf("WM_BUTTON1DOWN\n"); fflush(stdout);
770 #endif
771
772 pVideo = FSLib_GetUserParm(hwnd);
773 if (pVideo)
774 {
775 SDL_PrivateMouseButton(SDL_PRESSED,
776 SDL_BUTTON_LEFT,
777 0, 0); // Don't report mouse movement!
778
779 if (bMouseCapturable)
780 {
781 // We should capture the mouse!
782 if (!bMouseCaptured)
783 {
784 WinSetCapture(HWND_DESKTOP, hwnd);
785 WinSetPointer(HWND_DESKTOP, NULL);
786 bMouseCaptured = 1;
787 {
788 SWP swpClient;
789 POINTL ptl;
790 // Center the mouse to the middle of the window!
791 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
792 ptl.x = 0; ptl.y = 0;
793 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
794 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
795 WinSetPointerPos(HWND_DESKTOP,
796 ptl.x + swpClient.cx/2,
797 ptl.y + swpClient.cy/2);
798 }
799 }
800 }
801 }
802 break;
803 case WM_BUTTON1UP:
804 #ifdef DEBUG_BUILD
805 printf("WM_BUTTON1UP\n"); fflush(stdout);
806 #endif
807 SDL_PrivateMouseButton(SDL_RELEASED,
808 SDL_BUTTON_LEFT,
809 0, 0); // Don't report mouse movement!
810 break;
811 case WM_BUTTON2DOWN:
812 #ifdef DEBUG_BUILD
813 printf("WM_BUTTON2DOWN\n"); fflush(stdout);
814 #endif
815
816 pVideo = FSLib_GetUserParm(hwnd);
817 if (pVideo)
818 {
819 SDL_PrivateMouseButton(SDL_PRESSED,
820 SDL_BUTTON_RIGHT,
821 0, 0); // Don't report mouse movement!
822
823 if (bMouseCapturable)
824 {
825 // We should capture the mouse!
826 if (!bMouseCaptured)
827 {
828 WinSetCapture(HWND_DESKTOP, hwnd);
829 WinSetPointer(HWND_DESKTOP, NULL);
830 bMouseCaptured = 1;
831 {
832 SWP swpClient;
833 POINTL ptl;
834 // Center the mouse to the middle of the window!
835 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
836 ptl.x = 0; ptl.y = 0;
837 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
838 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
839 WinSetPointerPos(HWND_DESKTOP,
840 ptl.x + swpClient.cx/2,
841 ptl.y + swpClient.cy/2);
842 }
843 }
844 }
845
846 }
847 break;
848 case WM_BUTTON2UP:
849 #ifdef DEBUG_BUILD
850 printf("WM_BUTTON2UP\n"); fflush(stdout);
851 #endif
852 SDL_PrivateMouseButton(SDL_RELEASED,
853 SDL_BUTTON_RIGHT,
854 0, 0); // Don't report mouse movement!
855 break;
856 case WM_BUTTON3DOWN:
857 #ifdef DEBUG_BUILD
858 printf("WM_BUTTON3DOWN\n"); fflush(stdout);
859 #endif
860
861 pVideo = FSLib_GetUserParm(hwnd);
862 if (pVideo)
863 {
864 SDL_PrivateMouseButton(SDL_PRESSED,
865 SDL_BUTTON_MIDDLE,
866 0, 0); // Don't report mouse movement!
867
868 if (bMouseCapturable)
869 {
870 // We should capture the mouse!
871 if (!bMouseCaptured)
872 {
873 WinSetCapture(HWND_DESKTOP, hwnd);
874 WinSetPointer(HWND_DESKTOP, NULL);
875 bMouseCaptured = 1;
876 {
877 SWP swpClient;
878 POINTL ptl;
879 // Center the mouse to the middle of the window!
880 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
881 ptl.x = 0; ptl.y = 0;
882 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
883 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
884 WinSetPointerPos(HWND_DESKTOP,
885 ptl.x + swpClient.cx/2,
886 ptl.y + swpClient.cy/2);
887 }
888 }
889 }
890 }
891 break;
892 case WM_BUTTON3UP:
893 #ifdef DEBUG_BUILD
894 printf("WM_BUTTON3UP\n"); fflush(stdout);
895 #endif
896 SDL_PrivateMouseButton(SDL_RELEASED,
897 SDL_BUTTON_MIDDLE,
898 0, 0); // Don't report mouse movement!
899 break;
900 case WM_MOUSEMOVE:
901 #ifdef DEBUG_BUILD
902 // printf("WM_MOUSEMOVE\n"); fflush(stdout);
903 #endif
904
905 pVideo = FSLib_GetUserParm(hwnd);
906 if (pVideo)
907 {
908 if (pVideo->hidden->iSkipWMMOUSEMOVE)
909 {
910 pVideo->hidden->iSkipWMMOUSEMOVE--;
911 } else
912 {
913 POINTS *ppts = (POINTS *) (&mp1);
914 POINTL ptl;
915
916 if (bMouseCaptured)
917 {
918 SWP swpClient;
919
920 WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient);
921
922 // Send relative mouse position, and re-center the mouse
923 // Reposition the mouse to the center of the screen/window
924 SDL_PrivateMouseMotion(0, // Buttons not changed
925 1, // Relative position
926 ppts->x - (swpClient.cx/2),
927 (swpClient.cy/2) - ppts->y);
928
929 ptl.x = 0; ptl.y = 0;
930 WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
931 pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
932 // Center the mouse to the middle of the window!
933 WinSetPointerPos(HWND_DESKTOP,
934 ptl.x + swpClient.cx/2,
935 ptl.y + swpClient.cy/2);
936 } else
937 {
938 CONVERTMOUSEPOSITION();
939
940 // Send absolute mouse position
941 SDL_PrivateMouseMotion(0, // Buttons not changed
942 0, // Absolute position
943 ppts->x,
944 ppts->y);
945 }
946 }
947 if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured))
948 {
949 #ifdef DEBUG_BUILD
950 // printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout);
951 #endif
952
953 if (hptrGlobalPointer)
954 WinSetPointer(HWND_DESKTOP, hptrGlobalPointer);
955 else
956 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
957 }
958 else
959 {
960 WinSetPointer(HWND_DESKTOP, NULL);
961 }
962 }
963 #ifdef DEBUG_BUILD
964 // printf("WM_MOUSEMOVE done\n"); fflush(stdout);
965 #endif
966
967 return (MRESULT) FALSE;
968 case WM_CLOSE: // Window close
969 #ifdef DEBUG_BUILD
970 printf("WM_CLOSE\n"); fflush(stdout);
971 #endif
972
973 pVideo = FSLib_GetUserParm(hwnd);
974 if (pVideo)
975 {
976 // Send Quit message to the SDL application!
977 SDL_PrivateQuit();
978 return 0;
979 }
980 break;
981
982 #ifdef BITBLT_IN_WINMESSAGEPROC
983 case WM_UPDATERECTSREQUEST:
984 pVideo = FSLib_GetUserParm(hwnd);
985 if ((pVideo) && (pVideo->hidden->pSDLSurface))
986 {
987 if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
988 {
989 int numrects;
990 SDL_Rect *rects;
991 int i;
992 SWP swp;
993
994 numrects = (int) mp1;
995 rects = (SDL_Rect *) mp2;
996
997 WinQueryWindowPos(hwnd, &swp);
998 #ifndef RESIZE_EVEN_IF_RESIZABLE
999 if ((!pVideo->hidden->pSDLSurface) ||
1000 (
1001 (pVideo->hidden->pSDLSurface) &&
1002 (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
1003 ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) ||
1004 (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution)
1005 ) &&
1006 (!FSLib_QueryFSMode(hwnd))
1007 )
1008 )
1009 {
1010 // Resizable surface and in resizing!
1011 // So, don't blit now!
1012 #ifdef DEBUG_BUILD
1013 printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout);
1014 #endif
1015 } else
1016 #endif
1017 {
1018 #ifdef DEBUG_BUILD
1019 printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout);
1020 #endif
1021
1022 // Blit the changed areas
1023 for (i=0; i<numrects; i++)
1024 FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer,
1025 rects[i].y, rects[i].x, rects[i].w, rects[i].h);
1026 }
1027 DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer);
1028 }
1029 }
1030 return 0;
1031 #endif
1032
1033 default:
1034 #ifdef DEBUG_BUILD
1035 printf("Unhandled: %x\n", msg); fflush(stdout);
1036 #endif
1037
1038 break;
1039 }
1040 // Run the default window procedure for unhandled stuffs
1041 return WinDefWindowProc(hwnd, msg, mp1, mp2);
1042 }
1043
1044 /////////////////////////////////////////////////////////////////////
1045 //
1046 // FrameWndProc
1047 //
1048 // This is the message processing window procedure for the
1049 // frame window of SDLWindowClass.
1050 //
1051 /////////////////////////////////////////////////////////////////////
FrameWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)1052 static MRESULT EXPENTRY FrameWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1053 {
1054 PFNWP pOldFrameProc;
1055 MRESULT result;
1056 PTRACKINFO ti;
1057 int cx, cy, ncx, ncy;
1058 RECTL rclTemp;
1059 PSWP pswpTemp;
1060
1061 SDL_VideoDevice *pVideo = NULL;
1062
1063 pVideo = (SDL_VideoDevice *) WinQueryWindowULong(hwnd, QWL_USER);
1064
1065 pOldFrameProc = pVideo->hidden->pfnOldFrameProc;
1066
1067 if ((pVideo->hidden->bProportionalResize) &&
1068 (msg==WM_ADJUSTWINDOWPOS) &&
1069 (!FSLib_QueryFSMode(pVideo->hidden->hwndClient))
1070 )
1071 {
1072 pswpTemp = (PSWP) mp1;
1073
1074 /* Resizing? */
1075 if (pswpTemp->fl & SWP_SIZE)
1076 {
1077 /* Calculate client size */
1078 rclTemp.xLeft = pswpTemp->x;
1079 rclTemp.xRight = pswpTemp->x + pswpTemp->cx;
1080 rclTemp.yBottom = pswpTemp->y;
1081 rclTemp.yTop = pswpTemp->y + pswpTemp->cy;
1082 WinCalcFrameRect(hwnd, &rclTemp, TRUE);
1083
1084 ncx = cx = rclTemp.xRight - rclTemp.xLeft;
1085 ncy = cy = rclTemp.yTop - rclTemp.yBottom;
1086
1087 /* Calculate new size to keep it proportional */
1088
1089 if ((pVideo->hidden->ulResizingFlag & TF_LEFT) || (pVideo->hidden->ulResizingFlag & TF_RIGHT))
1090 {
1091 /* The window is resized horizontally */
1092 ncy = pVideo->hidden->SrcBufferDesc.uiYResolution * cx / pVideo->hidden->SrcBufferDesc.uiXResolution;
1093 } else
1094 if ((pVideo->hidden->ulResizingFlag & TF_TOP) || (pVideo->hidden->ulResizingFlag & TF_BOTTOM))
1095 {
1096 /* The window is resized vertically */
1097 ncx = pVideo->hidden->SrcBufferDesc.uiXResolution * cy / pVideo->hidden->SrcBufferDesc.uiYResolution;
1098 }
1099
1100 /* Calculate back frame coordinates */
1101 rclTemp.xLeft = pswpTemp->x;
1102 rclTemp.xRight = pswpTemp->x + ncx;
1103 rclTemp.yBottom = pswpTemp->y;
1104 rclTemp.yTop = pswpTemp->y + ncy;
1105 WinCalcFrameRect(hwnd, &rclTemp, FALSE);
1106
1107 /* Store new size/position info */
1108 pswpTemp->cx = rclTemp.xRight - rclTemp.xLeft;
1109
1110 if (!(pVideo->hidden->ulResizingFlag & TF_TOP))
1111 {
1112 pswpTemp->y = pswpTemp->y + pswpTemp->cy - (rclTemp.yTop - rclTemp.yBottom);
1113 pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom;
1114 } else
1115 {
1116 pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom;
1117 }
1118 }
1119 }
1120
1121 result = (*pOldFrameProc)(hwnd, msg, mp1, mp2);
1122
1123 if ((pVideo->hidden->bProportionalResize) && (msg==WM_QUERYTRACKINFO))
1124 {
1125 ti = (PTRACKINFO) mp2;
1126
1127 /* Store the direction of resizing */
1128 if ((ti->fs & TF_LEFT) || (ti->fs & TF_RIGHT) ||
1129 (ti->fs & TF_TOP) || (ti->fs & TF_BOTTOM))
1130 pVideo->hidden->ulResizingFlag = ti->fs;
1131 }
1132
1133 return result;
1134 }
1135
1136 /////////////////////////////////////////////////////////////////////
1137 //
1138 // PMThreadFunc
1139 //
1140 // This function implements the PM-Thread, which initializes the
1141 // application window itself, the DIVE, and start message processing.
1142 //
1143 /////////////////////////////////////////////////////////////////////
1144 int iNumOfPMThreadInstances = 0; // Global!
PMThreadFunc(void * pParm)1145 static void PMThreadFunc(void *pParm)
1146 {
1147 SDL_VideoDevice *pVideo = pParm;
1148 HAB hab;
1149 HMQ hmq;
1150 QMSG msg;
1151 ULONG fcf;
1152
1153 #ifdef DEBUG_BUILD
1154 printf("[PMThreadFunc] : Starting\n"); fflush(stdout);
1155 #endif
1156
1157 iNumOfPMThreadInstances++;
1158
1159 // Initialize PM, create a message queue.
1160
1161 hab=WinInitialize(0);
1162 hmq=WinCreateMsgQueue(hab,0);
1163 if (hmq==0)
1164 {
1165 #ifdef DEBUG_BUILD
1166 printf("[PMThreadFunc] : Could not create message queue!\n");
1167 printf(" It might be that the application using SDL is not a PM app!\n");
1168 fflush(stdout);
1169 #endif
1170 pVideo->hidden->iPMThreadStatus = 2;
1171 } else
1172 {
1173 int rc;
1174 RECTL rectl;
1175
1176 fcf = ulFCFToUse; // Get from global setting
1177
1178 #ifdef DEBUG_BUILD
1179 printf("[PMThreadFunc] : FSLib_CreateWindow()!\n");
1180 fflush(stdout);
1181 #endif
1182
1183 rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf,
1184 "SDL Application",
1185 NULLHANDLE, 0,
1186 &(pVideo->hidden->SrcBufferDesc),
1187 WndProc,
1188 &(pVideo->hidden->hwndClient),
1189 &(pVideo->hidden->hwndFrame));
1190
1191 #ifdef DEBUG_BUILD
1192 printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc);
1193 fflush(stdout);
1194 #endif
1195
1196 if (!rc)
1197 {
1198 #ifdef DEBUG_BUILD
1199 printf("[PMThreadFunc] : Could not create FSLib window!\n");
1200 fflush(stdout);
1201 #endif
1202 pVideo->hidden->iPMThreadStatus = 3;
1203 } else
1204 {
1205 #ifdef DEBUG_BUILD
1206 printf("[PMThreadFunc] : FSLib_AddUserParm()!\n");
1207 fflush(stdout);
1208 #endif
1209
1210 // Store pVideo pointer in window data for client window, so
1211 // it will know the instance to which it belongs to.
1212 FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo);
1213
1214 // Now set default image width height and fourcc!
1215 #ifdef DEBUG_BUILD
1216 printf("[PMThreadFunc] : SetWindowPos()!\n");
1217 fflush(stdout);
1218 #endif
1219
1220 // Set the position and size of the main window,
1221 // and make it visible!
1222 // Calculate frame window size from client window size
1223 rectl.xLeft = 0;
1224 rectl.yBottom = 0;
1225 rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive
1226 rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive
1227 WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE);
1228
1229 SetAccessableWindowPos(pVideo->hidden->hwndFrame,
1230 HWND_TOP,
1231 (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2,
1232 (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2,
1233 (rectl.xRight-rectl.xLeft),
1234 (rectl.yTop-rectl.yBottom),
1235 SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE);
1236
1237 // Subclass frame procedure and store old window proc address
1238 pVideo->hidden->pfnOldFrameProc =
1239 WinSubclassWindow(pVideo->hidden->hwndFrame, FrameWndProc);
1240 WinSetWindowULong(pVideo->hidden->hwndFrame, QWL_USER, (ULONG) pVideo);
1241
1242 #ifdef DEBUG_BUILD
1243 printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout);
1244 #endif
1245 pVideo->hidden->iPMThreadStatus = 1;
1246
1247 while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0))
1248 WinDispatchMsg(hab, (PQMSG) &msg);
1249
1250 #ifdef DEBUG_BUILD
1251 printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout);
1252 #endif
1253 // We should release the captured the mouse!
1254 if (bMouseCaptured)
1255 {
1256 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
1257 bMouseCaptured = 0;
1258 }
1259 // Destroy our window
1260 WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL;
1261 // Show pointer to make sure it will not be left hidden.
1262 WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE));
1263 WinShowPointer(HWND_DESKTOP, TRUE);
1264 }
1265 // Uninitialize PM
1266 WinDestroyMsgQueue(hmq);
1267 // All done!
1268 pVideo->hidden->iPMThreadStatus = 0;
1269 }
1270 WinTerminate(hab);
1271 /* Commented out, should not be needed anymore, because we send it
1272 from WM_CLOSE.
1273 // Notify SDL that it should really die now...
1274 SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :))
1275 */
1276 #ifdef DEBUG_BUILD
1277 printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout);
1278 #endif
1279
1280 iNumOfPMThreadInstances--;
1281
1282 // HACK to prevent zombie and hanging SDL applications, which does not take
1283 // care of closing the window for some reason:
1284 // There are some apps which do not process messages, so do a lot of things
1285 // without noticing that the application should close. To close these,
1286 // I've thought about the following:
1287 // If the window is closed (the execution came here), I wait a bit to
1288 // give time to the app to finish its execution. If it does not, I kill it
1289 // using DosExit(). Brute force, but should work.
1290 if (pVideo->hidden->iPMThreadStatus==0)
1291 {
1292 DosSleep(5000); // Wait 5 secs
1293 // If a new PM thread has been spawned (reinitializing video mode), then all right.
1294 // Otherwise, we have a problem, the app doesn't want to stop. Kill!
1295 if (iNumOfPMThreadInstances==0)
1296 {
1297 #ifdef DEBUG_BUILD
1298 printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout);
1299 printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout);
1300 printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout);
1301 #endif
1302 DosExit(EXIT_PROCESS, -1);
1303 }
1304 }
1305 _endthread();
1306 }
1307
1308 struct WMcursor
1309 {
1310 HBITMAP hbm;
1311 HPOINTER hptr;
1312 char *pchData;
1313 };
1314
1315 /* Free a window manager cursor */
os2fslib_FreeWMCursor(_THIS,WMcursor * cursor)1316 void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor)
1317 {
1318 if (cursor)
1319 {
1320 GpiDeleteBitmap(cursor->hbm);
1321 WinDestroyPointer(cursor->hptr);
1322 SDL_free(cursor->pchData);
1323 SDL_free(cursor);
1324 }
1325 }
1326
1327 /* Local functions to convert the SDL cursor mask into OS/2 format */
memnot(Uint8 * dst,Uint8 * src,int len)1328 static void memnot(Uint8 *dst, Uint8 *src, int len)
1329 {
1330 while ( len-- > 0 )
1331 *dst++ = ~*src++;
1332 }
memxor(Uint8 * dst,Uint8 * src1,Uint8 * src2,int len)1333 static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len)
1334 {
1335 while ( len-- > 0 )
1336 *dst++ = (*src1++)^(*src2++);
1337 }
1338
1339 /* Create a black/white window manager cursor */
os2fslib_CreateWMCursor_Win(_THIS,Uint8 * data,Uint8 * mask,int w,int h,int hot_x,int hot_y)1340 WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask,
1341 int w, int h, int hot_x, int hot_y)
1342 {
1343 HPOINTER hptr;
1344 HBITMAP hbm;
1345 BITMAPINFOHEADER bmih;
1346 BMPINFO bmi;
1347 HPS hps;
1348 char *pchTemp;
1349 char *xptr, *aptr;
1350 int maxx, maxy;
1351 int i, run, pad;
1352 WMcursor *pResult;
1353
1354 maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER);
1355 maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
1356
1357 // Check for max size!
1358 if ((w>maxx) || (h>maxy))
1359 return (WMcursor *) NULL;
1360
1361 pResult = (WMcursor *) SDL_malloc(sizeof(WMcursor));
1362 if (!pResult) return (WMcursor *) NULL;
1363
1364 pchTemp = (char *) SDL_malloc((maxx + 7)/8 * maxy*2);
1365 if (!pchTemp)
1366 {
1367 SDL_free(pResult);
1368 return (WMcursor *) NULL;
1369 }
1370
1371 SDL_memset(pchTemp, 0, (maxx + 7)/8 * maxy*2);
1372
1373 hps = WinGetPS(_this->hidden->hwndClient);
1374
1375 bmi.cbFix = sizeof(BITMAPINFOHEADER);
1376 bmi.cx = maxx;
1377 bmi.cy = 2*maxy;
1378 bmi.cPlanes = 1;
1379 bmi.cBitCount = 1;
1380 bmi.argbColor[0].bBlue = 0x00;
1381 bmi.argbColor[0].bGreen = 0x00;
1382 bmi.argbColor[0].bRed = 0x00;
1383 bmi.argbColor[1].bBlue = 0x00;
1384 bmi.argbColor[1].bGreen = 0x00;
1385 bmi.argbColor[1].bRed = 0xff;
1386
1387 SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
1388 bmih.cbFix = sizeof(BITMAPINFOHEADER);
1389 bmih.cx = maxx;
1390 bmih.cy = 2*maxy;
1391 bmih.cPlanes = 1;
1392 bmih.cBitCount = 1;
1393
1394 run = (w+7)/8;
1395 pad = (maxx+7)/8 - run;
1396
1397 for (i=0; i<h; i++)
1398 {
1399 xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
1400 aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
1401 memxor(xptr, data, mask, run);
1402 xptr += run;
1403 data += run;
1404 memnot(aptr, mask, run);
1405 mask += run;
1406 aptr += run;
1407 SDL_memset(xptr, 0, pad);
1408 xptr += pad;
1409 SDL_memset(aptr, ~0, pad);
1410 aptr += pad;
1411 }
1412 pad += run;
1413 for (i=h ; i<maxy; i++ )
1414 {
1415 xptr = pchTemp + (maxx+7)/8 * (maxy-1-i);
1416 aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i);
1417
1418 SDL_memset(xptr, 0, (maxx+7)/8);
1419 xptr += (maxx+7)/8;
1420 SDL_memset(aptr, ~0, (maxx+7)/8);
1421 aptr += (maxx+7)/8;
1422 }
1423
1424 hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
1425 hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1);
1426
1427 #ifdef DEBUG_BUILD
1428 printf("HotSpot : %d ; %d\n", hot_x, hot_y);
1429 printf("HPS returned : %x\n", (ULONG)hps);
1430 printf("HBITMAP returned : %x\n", (ULONG)hbm);
1431 printf("HPOINTER returned: %x\n", (ULONG)hptr);
1432 #endif
1433
1434 WinReleasePS(hps);
1435
1436 #ifdef DEBUG_BUILD
1437 printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout);
1438 #endif
1439
1440 pResult->hptr = hptr;
1441 pResult->hbm = hbm;
1442 pResult->pchData = pchTemp;
1443
1444 #ifdef DEBUG_BUILD
1445 printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout);
1446 #endif
1447
1448 return (WMcursor *) pResult;
1449 }
1450
os2fslib_CreateWMCursor_FS(_THIS,Uint8 * data,Uint8 * mask,int w,int h,int hot_x,int hot_y)1451 WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask,
1452 int w, int h, int hot_x, int hot_y)
1453 {
1454 #ifdef DEBUG_BUILD
1455 printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout);
1456 #endif
1457
1458 // In FS mode we'll use software cursor
1459 return (WMcursor *) NULL;
1460 }
1461
1462 /* Show the specified cursor, or hide if cursor is NULL */
os2fslib_ShowWMCursor(_THIS,WMcursor * cursor)1463 int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor)
1464 {
1465 #ifdef DEBUG_BUILD
1466 printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout);
1467 #endif
1468
1469 if (cursor)
1470 {
1471 WinSetPointer(HWND_DESKTOP, cursor->hptr);
1472 hptrGlobalPointer = cursor->hptr;
1473 _this->hidden->iMouseVisible = 1;
1474 }
1475 else
1476 {
1477 WinSetPointer(HWND_DESKTOP, FALSE);
1478 hptrGlobalPointer = NULL;
1479 _this->hidden->iMouseVisible = 0;
1480 }
1481
1482 #ifdef DEBUG_BUILD
1483 printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout);
1484 #endif
1485
1486 return 1;
1487 }
1488
1489 /* Warp the window manager cursor to (x,y)
1490 If NULL, a mouse motion event is posted internally.
1491 */
os2fslib_WarpWMCursor(_THIS,Uint16 x,Uint16 y)1492 void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
1493 {
1494 LONG lx, ly;
1495 SWP swpClient;
1496 POINTL ptlPoints;
1497 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
1498 ptlPoints.x = swpClient.x;
1499 ptlPoints.y = swpClient.y;
1500 WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1);
1501 lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution;
1502 ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1;
1503
1504 SDL_PrivateMouseMotion(0, // Buttons not changed
1505 0, // Absolute position
1506 x,
1507 y);
1508
1509 WinSetPointerPos(HWND_DESKTOP, lx, ly);
1510
1511 }
1512
1513 /* If not NULL, this is called when a mouse motion event occurs */
os2fslib_MoveWMCursor(_THIS,int x,int y)1514 void os2fslib_MoveWMCursor(_THIS, int x, int y)
1515 {
1516 /*
1517 SDL_Rect rect;
1518
1519 #ifdef DEBUG_BUILD
1520 printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout);
1521 #endif
1522
1523 rect.x = x;
1524 rect.y = y;
1525 rect.w = 32;
1526 rect.h = 32;
1527 os2fslib_UpdateRects(_this, 1, &rect);
1528 // TODO!
1529 */
1530 }
1531
1532 /* Determine whether the mouse should be in relative mode or not.
1533 This function is called when the input grab state or cursor
1534 visibility state changes.
1535 If the cursor is not visible, and the input is grabbed, the
1536 driver can place the mouse in relative mode, which may result
1537 in higher accuracy sampling of the pointer motion.
1538 */
os2fslib_CheckMouseMode(_THIS)1539 void os2fslib_CheckMouseMode(_THIS)
1540 {
1541 }
1542
os2fslib_PumpEvents(_THIS)1543 static void os2fslib_PumpEvents(_THIS)
1544 {
1545 // Notify SDL that if window has been resized!
1546 if (
1547 (_this->hidden->pSDLSurface) &&
1548 (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
1549 (
1550 (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) ||
1551 (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY)
1552 ) &&
1553 (iWindowSizeX>0) &&
1554 (iWindowSizeY>0)
1555 )
1556 {
1557 static time_t prev_time;
1558 time_t curr_time;
1559
1560 curr_time = time(NULL);
1561 if ((difftime(curr_time, prev_time)>=0.25) ||
1562 (bWindowResized))
1563 {
1564 // Make sure we won't flood the event queue with resize events,
1565 // only send them at 250 msecs!
1566 // (or when the window is resized)
1567 #ifdef DEBUG_BUILD
1568 printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n",
1569 iWindowSizeX, iWindowSizeY);
1570 fflush(stdout);
1571 #endif
1572 // Tell SDL the new size
1573 SDL_PrivateResize(iWindowSizeX, iWindowSizeY);
1574 prev_time = curr_time;
1575 bWindowResized = 0;
1576 }
1577 }
1578 }
1579
1580 /* We don't actually allow hardware surfaces other than the main one */
os2fslib_AllocHWSurface(_THIS,SDL_Surface * surface)1581 static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface)
1582 {
1583 return(-1);
1584 }
os2fslib_FreeHWSurface(_THIS,SDL_Surface * surface)1585 static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface)
1586 {
1587 return;
1588 }
1589
1590 /* We need to wait for vertical retrace on page flipped displays */
os2fslib_LockHWSurface(_THIS,SDL_Surface * surface)1591 static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface)
1592 {
1593 return(0);
1594 }
1595
os2fslib_UnlockHWSurface(_THIS,SDL_Surface * surface)1596 static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface)
1597 {
1598 return;
1599 }
1600
os2fslib_SetColors(_THIS,int firstcolor,int ncolors,SDL_Color * colors)1601 static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1602 {
1603 printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout);
1604 // TODO: Implement paletted modes
1605 return(1);
1606 }
1607
os2fslib_DestroyIcon(HWND hwndFrame)1608 static void os2fslib_DestroyIcon(HWND hwndFrame)
1609 {
1610 if (hptrCurrentIcon)
1611 {
1612 WinDestroyPointer(hptrCurrentIcon);
1613 hptrCurrentIcon = NULL;
1614
1615 WinSendMsg(hwndFrame,
1616 WM_SETICON,
1617 NULL,
1618 NULL);
1619 }
1620
1621 }
1622
1623 /* Set the window icon image */
os2fslib_SetIcon(_THIS,SDL_Surface * icon,Uint8 * mask)1624 void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
1625 {
1626 HWND hwndFrame;
1627 SDL_Surface *icon_rgb;
1628 HPOINTER hptrIcon;
1629 HBITMAP hbm;
1630 BITMAPINFOHEADER bmih;
1631 BMPINFO bmi;
1632 HPS hps;
1633 char *pchTemp;
1634 char *pptr, *mptr, *dptr, *dmptr;
1635 int maxx, maxy, w, h, x, y;
1636 SDL_Rect bounds;
1637
1638 #ifdef DEBUG_BUILD
1639 printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout);
1640 #endif
1641
1642 hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT);
1643
1644 // Make sure the old icon resource will be free'd!
1645 os2fslib_DestroyIcon(hwndFrame);
1646
1647 if ((!icon) || (!mask))
1648 return;
1649
1650 w = icon->w;
1651 h = icon->h;
1652
1653 maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
1654 maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
1655
1656 // Check for max size!
1657 if ((w>maxx) || (h>maxy))
1658 return;
1659
1660 pchTemp = (char *) SDL_malloc(w * h*2 * 4);
1661 if (!pchTemp)
1662 return;
1663
1664 SDL_memset(pchTemp, 0, w * h*2 * 4);
1665
1666 // Convert surface to RGB, if it's not RGB yet!
1667 icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
1668 32, 0, 0, 0, 0);
1669 if ( icon_rgb == NULL )
1670 {
1671 SDL_free(pchTemp);
1672 return;
1673 }
1674 bounds.x = 0;
1675 bounds.y = 0;
1676 bounds.w = icon->w;
1677 bounds.h = icon->h;
1678 if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 )
1679 {
1680 SDL_FreeSurface(icon_rgb);
1681 SDL_free(pchTemp);
1682 return;
1683 }
1684
1685 /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */
1686
1687 // Pixels
1688 pptr = (char *) (icon_rgb->pixels);
1689 // Mask
1690 mptr = mask;
1691
1692 for (y=0; y<h; y++)
1693 {
1694 unsigned char uchMaskByte;
1695
1696 // Destination
1697 dptr = pchTemp + w*4 * (h-y-1);
1698 // Destination mask
1699 dmptr = pchTemp + w*h*4 + w*4 * (h-y-1);
1700
1701 for (x=0; x<w; x++)
1702 {
1703 if (x%8==0)
1704 {
1705 uchMaskByte = (unsigned char) (*mptr);
1706 mptr++;
1707 } else
1708 uchMaskByte <<= 1;
1709
1710 if (uchMaskByte & 0x80)
1711 {
1712 // Copy RGB
1713 *dptr++ = *pptr++;
1714 *dptr++ = *pptr++;
1715 *dptr++ = *pptr++;
1716 *dptr++ = *pptr++;
1717
1718 *dmptr++ = 0;
1719 *dmptr++ = 0;
1720 *dmptr++ = 0;
1721 *dmptr++ = 0;
1722 } else
1723 {
1724 // Set pixels to fully transparent
1725 *dptr++ = 0; pptr++;
1726 *dptr++ = 0; pptr++;
1727 *dptr++ = 0; pptr++;
1728 *dptr++ = 0; pptr++;
1729
1730 *dmptr++ = 255;
1731 *dmptr++ = 255;
1732 *dmptr++ = 255;
1733 *dmptr++ = 255;
1734 }
1735 }
1736 }
1737
1738 // There is no more need for the RGB surface
1739 SDL_FreeSurface(icon_rgb);
1740
1741 hps = WinGetPS(_this->hidden->hwndClient);
1742
1743 bmi.cbFix = sizeof(BITMAPINFOHEADER);
1744 bmi.cx = w;
1745 bmi.cy = 2*h;
1746 bmi.cPlanes = 1;
1747 bmi.cBitCount = 32;
1748
1749 SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
1750 bmih.cbFix = sizeof(BITMAPINFOHEADER);
1751 bmih.cx = w;
1752 bmih.cy = 2*h;
1753 bmih.cPlanes = 1;
1754 bmih.cBitCount = 32;
1755
1756 hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi);
1757 hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0);
1758
1759 WinReleasePS(hps);
1760
1761 // Free pixel array
1762 SDL_free(pchTemp);
1763
1764 // Change icon in frame window
1765 WinSendMsg(hwndFrame,
1766 WM_SETICON,
1767 (MPARAM) hptrIcon,
1768 NULL);
1769
1770 /*
1771 // Change icon in switchlist
1772 // Seems like it's not needed, the WM_SETICON already does it.
1773 {
1774 PID pidFrame;
1775 HSWITCH hswitchFrame;
1776 SWCNTRL swctl;
1777
1778 WinQueryWindowProcess(hwndFrame, &pidFrame, NULL);
1779 hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame);
1780 WinQuerySwitchEntry(hswitchFrame, &swctl);
1781
1782 swctl.hwndIcon = hptrIcon;
1783
1784 WinChangeSwitchEntry(hswitchFrame, &swctl);
1785 }
1786 */
1787
1788 // Store icon handle in global variable
1789 hptrCurrentIcon = hptrIcon;
1790 }
1791
1792 // ------------------------ REAL FUNCTIONS -----------------
1793
1794
os2fslib_SetCursorManagementFunctions(_THIS,int iForWindowedMode)1795 static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode)
1796 {
1797 if (iForWindowedMode)
1798 {
1799 _this->FreeWMCursor = os2fslib_FreeWMCursor;
1800 _this->CreateWMCursor = os2fslib_CreateWMCursor_Win;
1801 _this->ShowWMCursor = os2fslib_ShowWMCursor;
1802 _this->WarpWMCursor = os2fslib_WarpWMCursor;
1803 _this->MoveWMCursor = os2fslib_MoveWMCursor;
1804 _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
1805 } else
1806 {
1807 // We'll have software mouse cursor in FS mode!
1808 _this->FreeWMCursor = os2fslib_FreeWMCursor;
1809 _this->CreateWMCursor = os2fslib_CreateWMCursor_FS;
1810 _this->ShowWMCursor = os2fslib_ShowWMCursor;
1811 _this->WarpWMCursor = os2fslib_WarpWMCursor;
1812 _this->MoveWMCursor = os2fslib_MoveWMCursor;
1813 _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode;
1814 }
1815 }
1816
os2fslib_InitOSKeymap(_THIS)1817 static void os2fslib_InitOSKeymap(_THIS)
1818 {
1819 int i;
1820
1821 iShiftIsPressed = 0;
1822
1823 /* Map the VK and CH keysyms */
1824 for ( i=0; i<=255; ++i )
1825 HWScanKeyMap[i] = SDLK_UNKNOWN;
1826
1827 // First line of keyboard:
1828 HWScanKeyMap[0x1] = SDLK_ESCAPE;
1829 HWScanKeyMap[0x3b] = SDLK_F1;
1830 HWScanKeyMap[0x3c] = SDLK_F2;
1831 HWScanKeyMap[0x3d] = SDLK_F3;
1832 HWScanKeyMap[0x3e] = SDLK_F4;
1833 HWScanKeyMap[0x3f] = SDLK_F5;
1834 HWScanKeyMap[0x40] = SDLK_F6;
1835 HWScanKeyMap[0x41] = SDLK_F7;
1836 HWScanKeyMap[0x42] = SDLK_F8;
1837 HWScanKeyMap[0x43] = SDLK_F9;
1838 HWScanKeyMap[0x44] = SDLK_F10;
1839 HWScanKeyMap[0x57] = SDLK_F11;
1840 HWScanKeyMap[0x58] = SDLK_F12;
1841 HWScanKeyMap[0x5d] = SDLK_PRINT;
1842 HWScanKeyMap[0x46] = SDLK_SCROLLOCK;
1843 HWScanKeyMap[0x5f] = SDLK_PAUSE;
1844
1845 // Second line of keyboard:
1846 HWScanKeyMap[0x29] = SDLK_BACKQUOTE;
1847 HWScanKeyMap[0x2] = SDLK_1;
1848 HWScanKeyMap[0x3] = SDLK_2;
1849 HWScanKeyMap[0x4] = SDLK_3;
1850 HWScanKeyMap[0x5] = SDLK_4;
1851 HWScanKeyMap[0x6] = SDLK_5;
1852 HWScanKeyMap[0x7] = SDLK_6;
1853 HWScanKeyMap[0x8] = SDLK_7;
1854 HWScanKeyMap[0x9] = SDLK_8;
1855 HWScanKeyMap[0xa] = SDLK_9;
1856 HWScanKeyMap[0xb] = SDLK_0;
1857 HWScanKeyMap[0xc] = SDLK_MINUS;
1858 HWScanKeyMap[0xd] = SDLK_EQUALS;
1859 HWScanKeyMap[0xe] = SDLK_BACKSPACE;
1860 HWScanKeyMap[0x68] = SDLK_INSERT;
1861 HWScanKeyMap[0x60] = SDLK_HOME;
1862 HWScanKeyMap[0x62] = SDLK_PAGEUP;
1863 HWScanKeyMap[0x45] = SDLK_NUMLOCK;
1864 HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE;
1865 HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY;
1866 HWScanKeyMap[0x4a] = SDLK_KP_MINUS;
1867
1868 // Third line of keyboard:
1869 HWScanKeyMap[0xf] = SDLK_TAB;
1870 HWScanKeyMap[0x10] = SDLK_q;
1871 HWScanKeyMap[0x11] = SDLK_w;
1872 HWScanKeyMap[0x12] = SDLK_e;
1873 HWScanKeyMap[0x13] = SDLK_r;
1874 HWScanKeyMap[0x14] = SDLK_t;
1875 HWScanKeyMap[0x15] = SDLK_y;
1876 HWScanKeyMap[0x16] = SDLK_u;
1877 HWScanKeyMap[0x17] = SDLK_i;
1878 HWScanKeyMap[0x18] = SDLK_o;
1879 HWScanKeyMap[0x19] = SDLK_p;
1880 HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET;
1881 HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET;
1882 HWScanKeyMap[0x1c] = SDLK_RETURN;
1883 HWScanKeyMap[0x69] = SDLK_DELETE;
1884 HWScanKeyMap[0x65] = SDLK_END;
1885 HWScanKeyMap[0x67] = SDLK_PAGEDOWN;
1886 HWScanKeyMap[0x47] = SDLK_KP7;
1887 HWScanKeyMap[0x48] = SDLK_KP8;
1888 HWScanKeyMap[0x49] = SDLK_KP9;
1889 HWScanKeyMap[0x4e] = SDLK_KP_PLUS;
1890
1891 // Fourth line of keyboard:
1892 HWScanKeyMap[0x3a] = SDLK_CAPSLOCK;
1893 HWScanKeyMap[0x1e] = SDLK_a;
1894 HWScanKeyMap[0x1f] = SDLK_s;
1895 HWScanKeyMap[0x20] = SDLK_d;
1896 HWScanKeyMap[0x21] = SDLK_f;
1897 HWScanKeyMap[0x22] = SDLK_g;
1898 HWScanKeyMap[0x23] = SDLK_h;
1899 HWScanKeyMap[0x24] = SDLK_j;
1900 HWScanKeyMap[0x25] = SDLK_k;
1901 HWScanKeyMap[0x26] = SDLK_l;
1902 HWScanKeyMap[0x27] = SDLK_SEMICOLON;
1903 HWScanKeyMap[0x28] = SDLK_QUOTE;
1904 HWScanKeyMap[0x2b] = SDLK_BACKSLASH;
1905 HWScanKeyMap[0x4b] = SDLK_KP4;
1906 HWScanKeyMap[0x4c] = SDLK_KP5;
1907 HWScanKeyMap[0x4d] = SDLK_KP6;
1908
1909 // Fifth line of keyboard:
1910 HWScanKeyMap[0x2a] = SDLK_LSHIFT;
1911 HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard
1912 HWScanKeyMap[0x2c] = SDLK_z;
1913 HWScanKeyMap[0x2d] = SDLK_x;
1914 HWScanKeyMap[0x2e] = SDLK_c;
1915 HWScanKeyMap[0x2f] = SDLK_v;
1916 HWScanKeyMap[0x30] = SDLK_b;
1917 HWScanKeyMap[0x31] = SDLK_n;
1918 HWScanKeyMap[0x32] = SDLK_m;
1919 HWScanKeyMap[0x33] = SDLK_COMMA;
1920 HWScanKeyMap[0x34] = SDLK_PERIOD;
1921 HWScanKeyMap[0x35] = SDLK_SLASH;
1922 HWScanKeyMap[0x36] = SDLK_RSHIFT;
1923 HWScanKeyMap[0x61] = SDLK_UP;
1924 HWScanKeyMap[0x4f] = SDLK_KP1;
1925 HWScanKeyMap[0x50] = SDLK_KP2;
1926 HWScanKeyMap[0x51] = SDLK_KP3;
1927 HWScanKeyMap[0x5a] = SDLK_KP_ENTER;
1928
1929 // Sixth line of keyboard:
1930 HWScanKeyMap[0x1d] = SDLK_LCTRL;
1931 HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key
1932 HWScanKeyMap[0x38] = SDLK_LALT;
1933 HWScanKeyMap[0x39] = SDLK_SPACE;
1934 HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard...
1935 HWScanKeyMap[0x7f] = SDLK_RSUPER;
1936 HWScanKeyMap[0x7c] = SDLK_MENU;
1937 HWScanKeyMap[0x5b] = SDLK_RCTRL;
1938 HWScanKeyMap[0x63] = SDLK_LEFT;
1939 HWScanKeyMap[0x66] = SDLK_DOWN;
1940 HWScanKeyMap[0x64] = SDLK_RIGHT;
1941 HWScanKeyMap[0x52] = SDLK_KP0;
1942 HWScanKeyMap[0x53] = SDLK_KP_PERIOD;
1943 }
1944
1945
1946 /* Iconify the window.
1947 This function returns 1 if there is a window manager and the
1948 window was actually iconified, it returns 0 otherwise.
1949 */
os2fslib_IconifyWindow(_THIS)1950 int os2fslib_IconifyWindow(_THIS)
1951 {
1952 HAB hab;
1953 HMQ hmq;
1954 ERRORID hmqerror;
1955
1956 // If there is no more window, nothing we can do!
1957 if (_this->hidden->iPMThreadStatus!=1) return 0;
1958
1959 // Cannot do anything in fullscreen mode!
1960 if (FSLib_QueryFSMode(_this->hidden->hwndClient))
1961 return 0;
1962
1963 // Make sure this thread is prepared for using the Presentation Manager!
1964 hab = WinInitialize(0);
1965 hmq = WinCreateMsgQueue(hab,0);
1966 // Remember if there was an error at WinCreateMsgQueue(), because we don't
1967 // want to destroy somebody else's queue later. :)
1968 hmqerror = WinGetLastError(hab);
1969
1970 WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP,
1971 0, 0, 0, 0, SWP_MINIMIZE);
1972
1973 // Now destroy the message queue, if we've created it!
1974 if (ERRORIDERROR(hmqerror)==0)
1975 WinDestroyMsgQueue(hmq);
1976
1977 return 1;
1978 }
1979
os2fslib_GrabInput(_THIS,SDL_GrabMode mode)1980 static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode)
1981 {
1982 HAB hab;
1983 HMQ hmq;
1984 ERRORID hmqerror;
1985
1986
1987 // If there is no more window, nothing we can do!
1988 if (_this->hidden->iPMThreadStatus!=1)
1989 return SDL_GRAB_OFF;
1990
1991 // Make sure this thread is prepared for using the Presentation Manager!
1992 hab = WinInitialize(0);
1993 hmq = WinCreateMsgQueue(hab,0);
1994 // Remember if there was an error at WinCreateMsgQueue(), because we don't
1995 // want to destroy somebody else's queue later. :)
1996 hmqerror = WinGetLastError(hab);
1997
1998
1999 if (mode == SDL_GRAB_OFF)
2000 {
2001 #ifdef DEBUG_BUILD
2002 printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout);
2003 #endif
2004
2005 // Release the mouse
2006 bMouseCapturable = 0;
2007 if (bMouseCaptured)
2008 {
2009 WinSetCapture(HWND_DESKTOP, NULLHANDLE);
2010 bMouseCaptured = 0;
2011 }
2012 } else
2013 {
2014 #ifdef DEBUG_BUILD
2015 printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout);
2016 #endif
2017
2018 // Capture the mouse
2019 bMouseCapturable = 1;
2020 if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient)
2021 {
2022 WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient);
2023 bMouseCaptured = 1;
2024 {
2025 SWP swpClient;
2026 POINTL ptl;
2027 // Center the mouse to the middle of the window!
2028 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
2029 ptl.x = 0; ptl.y = 0;
2030 WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1);
2031 _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */
2032 WinSetPointerPos(HWND_DESKTOP,
2033 ptl.x + swpClient.cx/2,
2034 ptl.y + swpClient.cy/2);
2035 }
2036 }
2037 }
2038
2039 // Now destroy the message queue, if we've created it!
2040 if (ERRORIDERROR(hmqerror)==0)
2041 WinDestroyMsgQueue(hmq);
2042
2043 return mode;
2044 }
2045
2046 /* Set the title and icon text */
os2fslib_SetCaption(_THIS,const char * title,const char * icon)2047 static void os2fslib_SetCaption(_THIS, const char *title, const char *icon)
2048 {
2049 HAB hab;
2050 HMQ hmq;
2051 ERRORID hmqerror;
2052
2053 // If there is no more window, nothing we can do!
2054 if (_this->hidden->iPMThreadStatus!=1) return;
2055
2056 // Make sure this thread is prepared for using the Presentation Manager!
2057 hab = WinInitialize(0);
2058 hmq = WinCreateMsgQueue(hab,0);
2059 // Remember if there was an error at WinCreateMsgQueue(), because we don't
2060 // want to destroy somebody else's queue later. :)
2061 hmqerror = WinGetLastError(hab);
2062
2063 WinSetWindowText(_this->hidden->hwndFrame, (char *) title);
2064
2065 // Now destroy the message queue, if we've created it!
2066 if (ERRORIDERROR(hmqerror)==0)
2067 WinDestroyMsgQueue(hmq);
2068 }
2069
os2fslib_ToggleFullScreen(_THIS,int on)2070 static int os2fslib_ToggleFullScreen(_THIS, int on)
2071 {
2072 #ifdef DEBUG_BUILD
2073 printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout);
2074 #endif
2075 // If there is no more window, nothing we can do!
2076 if (_this->hidden->iPMThreadStatus!=1) return 0;
2077
2078 FSLib_ToggleFSMode(_this->hidden->hwndClient, on);
2079 /* Cursor manager functions to Windowed/FS mode*/
2080 os2fslib_SetCursorManagementFunctions(_this, !on);
2081 return 1;
2082 }
2083
2084 /* This is called after the video mode has been set, to get the
2085 initial mouse state. It should queue events as necessary to
2086 properly represent the current mouse focus and position.
2087 */
os2fslib_UpdateMouse(_THIS)2088 static void os2fslib_UpdateMouse(_THIS)
2089 {
2090 POINTL ptl;
2091 HAB hab;
2092 HMQ hmq;
2093 ERRORID hmqerror;
2094 SWP swpClient;
2095
2096 // If there is no more window, nothing we can do!
2097 if (_this->hidden->iPMThreadStatus!=1) return;
2098
2099
2100 // Make sure this thread is prepared for using the Presentation Manager!
2101 hab = WinInitialize(0);
2102 hmq = WinCreateMsgQueue(hab,0);
2103 // Remember if there was an error at WinCreateMsgQueue(), because we don't
2104 // want to destroy somebody else's queue later. :)
2105 hmqerror = WinGetLastError(hab);
2106
2107
2108
2109 if (_this->hidden->fInFocus)
2110 {
2111 // If our app is in focus
2112 SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
2113 SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
2114 SDL_PrivateAppActive(1, SDL_APPACTIVE);
2115 WinQueryPointerPos(HWND_DESKTOP, &ptl);
2116 WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1);
2117 WinQueryWindowPos(_this->hidden->hwndClient, &swpClient);
2118 // Convert OS/2 mouse position to SDL position, and also scale it!
2119 ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx;
2120 ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy;
2121 ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1;
2122 SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y));
2123 } else
2124 {
2125 // If we're not in focus
2126 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
2127 SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
2128 SDL_PrivateAppActive(0, SDL_APPACTIVE);
2129 SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1);
2130 }
2131
2132 // Now destroy the message queue, if we've created it!
2133 if (ERRORIDERROR(hmqerror)==0)
2134 WinDestroyMsgQueue(hmq);
2135
2136 }
2137
2138 /* This pointer should exist in the native video subsystem and should
2139 point to an appropriate update function for the current video mode
2140 */
os2fslib_UpdateRects(_THIS,int numrects,SDL_Rect * rects)2141 static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
2142 {
2143 // If there is no more window, nothing we can do!
2144 if (_this->hidden->iPMThreadStatus!=1) return;
2145
2146 #ifdef BITBLT_IN_WINMESSAGEPROC
2147 WinSendMsg(_this->hidden->hwndClient,
2148 WM_UPDATERECTSREQUEST,
2149 (MPARAM) numrects,
2150 (MPARAM) rects);
2151 #else
2152 if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
2153 {
2154 int i;
2155
2156 if (_this->hidden->pSDLSurface)
2157 {
2158 #ifndef RESIZE_EVEN_IF_RESIZABLE
2159 SWP swp;
2160 // But only blit if the window is not resizable, or if
2161 // the window is resizable and the source buffer size is the
2162 // same as the destination buffer size!
2163 WinQueryWindowPos(_this->hidden->hwndClient, &swp);
2164 if ((_this->hidden->pSDLSurface) &&
2165 (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) &&
2166 ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) ||
2167 (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution)
2168 ) &&
2169 (!FSLib_QueryFSMode(_this->hidden->hwndClient))
2170 )
2171 {
2172 // Resizable surface and in resizing!
2173 // So, don't blit now!
2174 #ifdef DEBUG_BUILD
2175 printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout);
2176 #endif
2177 } else
2178 #endif
2179 {
2180 /*
2181 // Blit the whole window
2182 FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
2183 0, 0,
2184 _this->hidden->SrcBufferDesc.uiXResolution,
2185 _this->hidden->SrcBufferDesc.uiYResolution);
2186 */
2187 #ifdef DEBUG_BUILD
2188 printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout);
2189 #endif
2190
2191 // Blit the changed areas
2192 for (i=0; i<numrects; i++)
2193 FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer,
2194 rects[i].y, rects[i].x, rects[i].w, rects[i].h);
2195 }
2196 }
2197 #ifdef DEBUG_BUILD
2198 else
2199 printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout);
2200 #endif
2201 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
2202 }
2203 #ifdef DEBUG_BUILD
2204 else
2205 printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout);
2206 #endif
2207 #endif
2208 }
2209
2210
2211 /* Reverse the effects VideoInit() -- called if VideoInit() fails
2212 or if the application is shutting down the video subsystem.
2213 */
os2fslib_VideoQuit(_THIS)2214 static void os2fslib_VideoQuit(_THIS)
2215 {
2216 #ifdef DEBUG_BUILD
2217 printf("[os2fslib_VideoQuit]\n"); fflush(stdout);
2218 #endif
2219 // Close PM stuff if running!
2220 if (_this->hidden->iPMThreadStatus == 1)
2221 {
2222 int iTimeout;
2223 WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0);
2224 // HACK: We had this line before:
2225 //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT);
2226 // We don't use it, because the PMThread will never stop, or if it stops,
2227 // it will kill the whole process as a emergency fallback.
2228 // So, we only check for the iPMThreadStatus stuff!
2229 #ifdef DEBUG_BUILD
2230 printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout);
2231 #endif
2232
2233 iTimeout=0;
2234 while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100))
2235 {
2236 iTimeout++;
2237 DosSleep(64);
2238 }
2239
2240 #ifdef DEBUG_BUILD
2241 printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout);
2242 #endif
2243
2244 if (_this->hidden->iPMThreadStatus == 1)
2245 {
2246 #ifdef DEBUG_BUILD
2247 printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout);
2248 #endif
2249
2250 _this->hidden->iPMThreadStatus = 0;
2251 DosKillThread(_this->hidden->tidPMThread);
2252
2253 if (_this->hidden->hwndFrame)
2254 {
2255 #ifdef DEBUG_BUILD
2256 printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout);
2257 #endif
2258
2259 WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL;
2260 }
2261 }
2262
2263 }
2264
2265 // Free result of an old ListModes() call, because there is
2266 // no FreeListModes() call in SDL!
2267 if (_this->hidden->pListModesResult)
2268 {
2269 SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
2270 }
2271
2272 // Free list of available fullscreen modes
2273 if (_this->hidden->pAvailableFSLibVideoModes)
2274 {
2275 FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
2276 _this->hidden->pAvailableFSLibVideoModes = NULL;
2277 }
2278
2279 // Free application icon if we had one
2280 if (hptrCurrentIcon)
2281 {
2282 WinDestroyPointer(hptrCurrentIcon);
2283 hptrCurrentIcon = NULL;
2284 }
2285 }
2286
2287 /* Set the requested video mode, returning a surface which will be
2288 set to the SDL_VideoSurface. The width and height will already
2289 be verified by ListModes(), and the video subsystem is free to
2290 set the mode to a supported bit depth different from the one
2291 specified -- the desired bpp will be emulated with a shadow
2292 surface if necessary. If a new mode is returned, this function
2293 should take care of cleaning up the current mode.
2294 */
os2fslib_SetVideoMode(_THIS,SDL_Surface * current,int width,int height,int bpp,Uint32 flags)2295 static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current,
2296 int width, int height, int bpp, Uint32 flags)
2297 {
2298 static int bFirstCall = 1;
2299 FSLib_VideoMode_p pModeInfo, pModeInfoFound;
2300 FSLib_VideoMode TempModeInfo;
2301 HAB hab;
2302 HMQ hmq;
2303 ERRORID hmqerror;
2304 RECTL rectl;
2305 SDL_Surface *pResult;
2306
2307 // If there is no more window, nothing we can do!
2308 if (_this->hidden->iPMThreadStatus!=1) return NULL;
2309
2310 #ifdef DEBUG_BUILD
2311 printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
2312 #endif
2313
2314 // We don't support palette modes!
2315 if (bpp==8) bpp=32;
2316
2317 // Also, we don't support resizable modes in fullscreen mode.
2318 if (flags & SDL_RESIZABLE)
2319 flags &= ~SDL_FULLSCREEN;
2320
2321 // No double buffered mode
2322 if (flags & SDL_DOUBLEBUF)
2323 flags &= ~SDL_DOUBLEBUF;
2324
2325 // And, we don't support HWSURFACE yet.
2326 if (flags & SDL_HWSURFACE)
2327 {
2328 flags &= ~SDL_HWSURFACE;
2329 flags |= SDL_SWSURFACE;
2330 }
2331
2332 #ifdef DEBUG_BUILD
2333 printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout);
2334 #endif
2335
2336 // First check if there is such a video mode they want!
2337 pModeInfoFound = NULL;
2338
2339 // For fullscreen mode we don't support every resolution!
2340 // So, go through the video modes, and check for such a resolution!
2341 pModeInfoFound = NULL;
2342 pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
2343
2344 while (pModeInfo)
2345 {
2346 // Check all available fullscreen modes for this resolution
2347 if ((pModeInfo->uiXResolution == width) &&
2348 (pModeInfo->uiYResolution == height) &&
2349 (pModeInfo->uiBPP!=8)) // palettized modes not yet supported
2350 {
2351 // If good resolution, try to find the exact BPP, or at least
2352 // something similar...
2353 if (!pModeInfoFound)
2354 pModeInfoFound = pModeInfo;
2355 else
2356 if ((pModeInfoFound->uiBPP!=bpp) &&
2357 (pModeInfoFound->uiBPP<pModeInfo->uiBPP))
2358 pModeInfoFound = pModeInfo;
2359 }
2360 pModeInfo = pModeInfo->pNext;
2361 }
2362
2363 // If we did not find a good fullscreen mode, then try a similar
2364 if (!pModeInfoFound)
2365 {
2366 #ifdef DEBUG_BUILD
2367 printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout);
2368 #endif
2369 // Go through the video modes again, and find a similar resolution!
2370 pModeInfo = _this->hidden->pAvailableFSLibVideoModes;
2371 while (pModeInfo)
2372 {
2373 // Check all available fullscreen modes for this resolution
2374 if ((pModeInfo->uiXResolution >= width) &&
2375 (pModeInfo->uiYResolution >= height) &&
2376 (pModeInfo->uiBPP == bpp))
2377 {
2378 if (!pModeInfoFound)
2379 pModeInfoFound = pModeInfo;
2380 else
2381 if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))>
2382 ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height)))
2383 {
2384 // Found a mode which is closer than the current one
2385 pModeInfoFound = pModeInfo;
2386 }
2387 }
2388 pModeInfo = pModeInfo->pNext;
2389 }
2390 }
2391
2392 // If we did not find a good fullscreen mode, then return NULL
2393 if (!pModeInfoFound)
2394 {
2395 #ifdef DEBUG_BUILD
2396 printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout);
2397 #endif
2398 return NULL;
2399 }
2400
2401 #ifdef DEBUG_BUILD
2402 printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout);
2403 #endif
2404
2405 // We'll possibly adjust the structure, so copy out the values
2406 // into TempModeInfo!
2407 SDL_memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo));
2408 pModeInfoFound = &TempModeInfo;
2409
2410 if (flags & SDL_RESIZABLE)
2411 {
2412 #ifdef DEBUG_BUILD
2413 printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout);
2414 #endif
2415 // Change width and height to requested one!
2416 TempModeInfo.uiXResolution = width;
2417 TempModeInfo.uiYResolution = height;
2418 TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8);
2419 }
2420
2421 // We can try create new surface!
2422
2423 // Make sure this thread is prepared for using the Presentation Manager!
2424 hab = WinInitialize(0);
2425 hmq = WinCreateMsgQueue(hab,0);
2426 // Remember if there was an error at WinCreateMsgQueue(), because we don't
2427 // want to destroy somebody else's queue later. :)
2428 hmqerror = WinGetLastError(hab);
2429
2430
2431
2432 if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR)
2433 {
2434 #ifdef DEBUG_BUILD
2435 printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout);
2436 #endif
2437
2438 // Create new software surface!
2439 pResult = SDL_CreateRGBSurface(SDL_SWSURFACE,
2440 pModeInfoFound->uiXResolution,
2441 pModeInfoFound->uiYResolution,
2442 pModeInfoFound->uiBPP,
2443 ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition,
2444 ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition,
2445 ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition,
2446 ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition);
2447
2448 if (pResult == NULL)
2449 {
2450 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
2451 SDL_OutOfMemory();
2452 return NULL;
2453 }
2454
2455 #ifdef DEBUG_BUILD
2456 printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout);
2457 #endif
2458
2459 // Adjust pixel format mask!
2460 pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition;
2461 pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition;
2462 pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust;
2463 pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition;
2464 pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition;
2465 pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust;
2466 pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition;
2467 pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition;
2468 pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust;
2469 pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition;
2470 pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition;
2471 pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust;
2472
2473 #ifdef REPORT_EMPTY_ALPHA_MASK
2474 pResult->format->Amask =
2475 pResult->format->Ashift =
2476 pResult->format->Aloss = 0;
2477 #endif
2478
2479 // Adjust surface flags
2480 pResult->flags |= (flags & SDL_FULLSCREEN);
2481 pResult->flags |= (flags & SDL_RESIZABLE);
2482
2483 // It might be that the software surface pitch is not the same as
2484 // the pitch we have, so adjust that!
2485 pModeInfoFound->uiScanLineSize = pResult->pitch;
2486
2487 // Store new source buffer parameters!
2488 SDL_memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound));
2489 _this->hidden->pchSrcBuffer = pResult->pixels;
2490
2491 #ifdef DEBUG_BUILD
2492 printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout);
2493 #endif
2494
2495 // Tell the FSLib window the new source image format
2496 FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc));
2497
2498 if (
2499 ((flags & SDL_RESIZABLE)==0) ||
2500 (bFirstCall)
2501 )
2502 {
2503 bFirstCall = 0;
2504 #ifdef DEBUG_BUILD
2505 printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout);
2506 #endif
2507
2508 // Calculate frame window size from client window size
2509 rectl.xLeft = 0;
2510 rectl.yBottom = 0;
2511 rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive
2512 rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive
2513 WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE);
2514
2515 // Set the new size of the main window
2516 SetAccessableWindowPos(_this->hidden->hwndFrame,
2517 HWND_TOP,
2518 0, 0,
2519 (rectl.xRight-rectl.xLeft),
2520 (rectl.yTop-rectl.yBottom),
2521 SWP_SIZE | SWP_ACTIVATE | SWP_SHOW);
2522 }
2523
2524 // Set fullscreen mode flag, and switch to fullscreen if needed!
2525 if (flags & SDL_FULLSCREEN)
2526 {
2527 #ifdef DEBUG_BUILD
2528 printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n");
2529 fflush(stdout);
2530 #endif
2531 FSLib_ToggleFSMode(_this->hidden->hwndClient, 1);
2532 /* Cursor manager functions to FS mode*/
2533 os2fslib_SetCursorManagementFunctions(_this, 0);
2534 } else
2535 {
2536 #ifdef DEBUG_BUILD
2537 printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n");
2538 fflush(stdout);
2539 #endif
2540 FSLib_ToggleFSMode(_this->hidden->hwndClient, 0);
2541 /* Cursor manager functions to Windowed mode*/
2542 os2fslib_SetCursorManagementFunctions(_this, 1);
2543 }
2544
2545 _this->hidden->pSDLSurface = pResult;
2546
2547 DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer);
2548 } else
2549 {
2550 #ifdef DEBUG_BUILD
2551 printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout);
2552 #endif
2553
2554 pResult = NULL;
2555 }
2556
2557 // As we have the new surface, we don't need the current one anymore!
2558 if ((pResult) && (current))
2559 {
2560 #ifdef DEBUG_BUILD
2561 printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout);
2562 #endif
2563 SDL_FreeSurface(current);
2564 }
2565
2566 // Redraw window
2567 WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE);
2568
2569 // Now destroy the message queue, if we've created it!
2570 if (ERRORIDERROR(hmqerror)==0)
2571 {
2572 #ifdef DEBUG_BUILD
2573 printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout);
2574 #endif
2575 WinDestroyMsgQueue(hmq);
2576 }
2577
2578 #ifdef DEBUG_BUILD
2579 printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout);
2580 #endif
2581
2582 /* We're done */
2583
2584 // Return with the new surface!
2585 return pResult;
2586 }
2587
2588 /* List the available video modes for the given pixel format, sorted
2589 from largest to smallest.
2590 */
os2fslib_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)2591 static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
2592 {
2593 #ifdef DEBUG_BUILD
2594 printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel);
2595 #endif
2596 // Destroy result of previous call, if there is any
2597 if (_this->hidden->pListModesResult)
2598 {
2599 SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL;
2600 }
2601
2602 // For resizable and windowed mode we support every resolution!
2603 if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0))
2604 return (SDL_Rect **)-1;
2605
2606 // Check if they need fullscreen or non-fullscreen video modes!
2607 if ((flags & SDL_FULLSCREEN) == 0)
2608
2609 {
2610 // For windowed mode we support every resolution!
2611 return (SDL_Rect **)-1;
2612 } else
2613 {
2614 FSLib_VideoMode_p pFSMode;
2615 // For fullscreen mode we don't support every resolution!
2616 // Now create a new list
2617 pFSMode = _this->hidden->pAvailableFSLibVideoModes;
2618 while (pFSMode)
2619 {
2620 if (pFSMode->uiBPP == format->BitsPerPixel)
2621 {
2622 SDL_Rect *pRect = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect));
2623 if (pRect)
2624 {
2625 // Fill description
2626 pRect->x = 0;
2627 pRect->y = 0;
2628 pRect->w = pFSMode->uiXResolution;
2629 pRect->h = pFSMode->uiYResolution;
2630 #ifdef DEBUG_BUILD
2631 // printf("!!! Seems to be good!\n");
2632 // printf("F: %dx%d\n", pRect->w, pRect->h);
2633 #endif
2634 // And insert into list of pRects
2635 if (!(_this->hidden->pListModesResult))
2636 {
2637 #ifdef DEBUG_BUILD
2638 // printf("!!! Inserting to beginning\n");
2639 #endif
2640
2641 // We're the first one to be inserted!
2642 _this->hidden->pListModesResult = (SDL_Rect**) SDL_malloc(2*sizeof(SDL_Rect*));
2643 if (_this->hidden->pListModesResult)
2644 {
2645 _this->hidden->pListModesResult[0] = pRect;
2646 _this->hidden->pListModesResult[1] = NULL;
2647 } else
2648 {
2649 SDL_free(pRect);
2650 }
2651 } else
2652 {
2653 // We're not the first ones, so find the place where we
2654 // have to insert ourselves
2655 SDL_Rect **pNewList;
2656 int iPlace, iNumOfSlots, i;
2657
2658 #ifdef DEBUG_BUILD
2659 // printf("!!! Searching where to insert\n");
2660 #endif
2661
2662 iPlace = -1; iNumOfSlots = 1; // Count the last NULL too!
2663 for (i=0; _this->hidden->pListModesResult[i]; i++)
2664 {
2665 iNumOfSlots++;
2666 if (iPlace==-1)
2667 {
2668 if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)<
2669 (pRect->w*pRect->h))
2670 {
2671 iPlace = i;
2672 }
2673 }
2674 }
2675 if (iPlace==-1) iPlace = iNumOfSlots-1;
2676
2677 #ifdef DEBUG_BUILD
2678 // printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace);
2679 #endif
2680
2681 pNewList = (SDL_Rect**) SDL_realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*));
2682 if (pNewList)
2683 {
2684 for (i=iNumOfSlots;i>iPlace;i--)
2685 pNewList[i] = pNewList[i-1];
2686 pNewList[iPlace] = pRect;
2687 _this->hidden->pListModesResult = pNewList;
2688 } else
2689 {
2690 SDL_free(pRect);
2691 }
2692 }
2693 }
2694 }
2695 pFSMode = pFSMode->pNext;
2696 }
2697 }
2698 #ifdef DEBUG_BUILD
2699 // printf("Returning list\n");
2700 #endif
2701 return _this->hidden->pListModesResult;
2702 }
2703
2704 /* Initialize the native video subsystem, filling 'vformat' with the
2705 "best" display pixel format, returning 0 or -1 if there's an error.
2706 */
os2fslib_VideoInit(_THIS,SDL_PixelFormat * vformat)2707 static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat)
2708 {
2709 FSLib_VideoMode_p pDesktopMode;
2710
2711 #ifdef DEBUG_BUILD
2712 printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout);
2713 #endif
2714
2715 // Report the best pixel format. For this,
2716 // we'll use the current desktop format.
2717 pDesktopMode = FSLib_GetDesktopVideoMode();
2718 if (!pDesktopMode)
2719 {
2720 SDL_SetError("Could not query desktop video mode!");
2721 #ifdef DEBUG_BUILD
2722 printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n");
2723 #endif
2724 return -1;
2725 }
2726
2727 /* Determine the current screen size */
2728 _this->info.current_w = pDesktopMode->uiXResolution;
2729 _this->info.current_h = pDesktopMode->uiYResolution;
2730
2731 /* Determine the screen depth */
2732 vformat->BitsPerPixel = pDesktopMode->uiBPP;
2733 vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8;
2734
2735 vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition;
2736 vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition;
2737 vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust;
2738 vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition;
2739 vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition;
2740 vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust;
2741 vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition;
2742 vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition;
2743 vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust;
2744 vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition;
2745 vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition;
2746 vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust;
2747
2748 #ifdef REPORT_EMPTY_ALPHA_MASK
2749 vformat->Amask =
2750 vformat->Ashift =
2751 vformat->Aloss = 0;
2752 #endif
2753
2754 // Fill in some window manager capabilities
2755 _this->info.wm_available = 1;
2756
2757 // Initialize some internal variables
2758 _this->hidden->pListModesResult = NULL;
2759 _this->hidden->fInFocus = 0;
2760 _this->hidden->iSkipWMMOUSEMOVE = 0;
2761 _this->hidden->iMouseVisible = 1;
2762
2763 if (getenv("SDL_USE_PROPORTIONAL_WINDOW"))
2764 _this->hidden->bProportionalResize = 1;
2765 else
2766 {
2767 PPIB pib;
2768 PTIB tib;
2769 char *pchFileName, *pchTemp;
2770 char achConfigFile[CCHMAXPATH];
2771 FILE *hFile;
2772
2773 /* No environment variable to have proportional window.
2774 * Ok, let's check if this executable is in config file!
2775 */
2776 _this->hidden->bProportionalResize = 0;
2777
2778 DosGetInfoBlocks(&tib, &pib);
2779 pchTemp = pchFileName = pib->pib_pchcmd;
2780 while (*pchTemp)
2781 {
2782 if (*pchTemp=='\\')
2783 pchFileName = pchTemp+1;
2784 pchTemp++;
2785 }
2786 if (getenv("HOME"))
2787 {
2788 sprintf(achConfigFile, "%s\\.sdl.proportionals", getenv("HOME"));
2789 hFile = fopen(achConfigFile, "rt");
2790 if (!hFile)
2791 {
2792 /* Seems like the file cannot be opened or does not exist.
2793 * Let's try to create it with defaults!
2794 */
2795 hFile = fopen(achConfigFile, "wt");
2796 if (hFile)
2797 {
2798 fprintf(hFile, "; This file is a config file of SDL/2, containing\n");
2799 fprintf(hFile, "; the list of executables that must have proportional\n");
2800 fprintf(hFile, "; windows.\n");
2801 fprintf(hFile, ";\n");
2802 fprintf(hFile, "; You can add executable filenames into this file,\n");
2803 fprintf(hFile, "; one under the other. If SDL finds that a given\n");
2804 fprintf(hFile, "; program is in this list, then that application\n");
2805 fprintf(hFile, "; will have proportional windows, just like if\n");
2806 fprintf(hFile, "; the SET SDL_USE_PROPORTIONAL_WINDOW env. variable\n");
2807 fprintf(hFile, "; would have been set for that process.\n");
2808 fprintf(hFile, ";\n");
2809 fprintf(hFile, "\n");
2810 fprintf(hFile, "dosbox.exe\n");
2811 fclose(hFile);
2812 }
2813
2814 hFile = fopen(achConfigFile, "rt");
2815 }
2816
2817 if (hFile)
2818 {
2819 while (fgets(achConfigFile, sizeof(achConfigFile), hFile))
2820 {
2821 /* Cut \n from end of string */
2822
2823 while (achConfigFile[strlen(achConfigFile)-1] == '\n')
2824 achConfigFile[strlen(achConfigFile)-1] = 0;
2825
2826 /* Compare... */
2827 if (stricmp(achConfigFile, pchFileName)==0)
2828 {
2829 /* Found it in config file! */
2830 _this->hidden->bProportionalResize = 1;
2831 break;
2832 }
2833 }
2834 fclose(hFile);
2835 }
2836 }
2837 }
2838
2839 DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE);
2840
2841 // Now create our window with a default size
2842
2843 // For this, we select the first available fullscreen mode as
2844 // current window size!
2845 SDL_memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc));
2846 // Allocate new video buffer!
2847 _this->hidden->pchSrcBuffer = (char *) SDL_malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution);
2848 if (!_this->hidden->pchSrcBuffer)
2849 {
2850 #ifdef DEBUG_BUILD
2851 printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout);
2852 #endif
2853 SDL_SetError("Not enough memory for new video buffer!\n");
2854 return -1;
2855 }
2856
2857 // For this, we need a message processing thread.
2858 // We'll create a new thread for this, which will do everything
2859 // what is related to PM
2860 _this->hidden->iPMThreadStatus = 0;
2861 _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this);
2862 if (_this->hidden->tidPMThread <= 0)
2863 {
2864 #ifdef DEBUG_BUILD
2865 printf("[os2fslib_VideoInit] : Could not create PM thread!\n");
2866 #endif
2867 SDL_SetError("Could not create PM thread");
2868 return -1;
2869 }
2870 #ifdef USE_DOSSETPRIORITY
2871 // Burst the priority of PM Thread!
2872 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread);
2873 #endif
2874 // Wait for the PM thread to initialize!
2875 while (_this->hidden->iPMThreadStatus==0)
2876 DosSleep(32);
2877 // If the PM thread could not set up everything, then
2878 // report an error!
2879 if (_this->hidden->iPMThreadStatus!=1)
2880 {
2881 #ifdef DEBUG_BUILD
2882 printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus);
2883 #endif
2884 SDL_SetError("Error initializing PM thread");
2885 return -1;
2886 }
2887
2888 return 0;
2889 }
2890
2891
os2fslib_DeleteDevice(_THIS)2892 static void os2fslib_DeleteDevice(_THIS)
2893 {
2894 #ifdef DEBUG_BUILD
2895 printf("[os2fslib_DeleteDevice]\n"); fflush(stdout);
2896 #endif
2897 // Free used memory
2898 FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes);
2899 if (_this->hidden->pListModesResult)
2900 SDL_free(_this->hidden->pListModesResult);
2901 if (_this->hidden->pchSrcBuffer)
2902 SDL_free(_this->hidden->pchSrcBuffer);
2903 DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer);
2904 SDL_free(_this->hidden);
2905 SDL_free(_this);
2906 FSLib_Uninitialize();
2907 }
2908
os2fslib_Available(void)2909 static int os2fslib_Available(void)
2910 {
2911
2912 // If we can run, it means that we could load FSLib,
2913 // so we assume that it's available then!
2914 return 1;
2915 }
2916
os2fslib_MorphToPM()2917 static void os2fslib_MorphToPM()
2918 {
2919 PPIB pib;
2920 PTIB tib;
2921
2922 DosGetInfoBlocks(&tib, &pib);
2923
2924 // Change flag from VIO to PM:
2925 if (pib->pib_ultype==2) pib->pib_ultype = 3;
2926 }
2927
os2fslib_CreateDevice(int devindex)2928 static SDL_VideoDevice *os2fslib_CreateDevice(int devindex)
2929 {
2930 SDL_VideoDevice *device;
2931
2932 #ifdef DEBUG_BUILD
2933 printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout);
2934 #endif
2935
2936 /* Initialize all variables that we clean on shutdown */
2937 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
2938 if ( device )
2939 {
2940 SDL_memset(device, 0, (sizeof *device));
2941 // Also allocate memory for private data
2942 device->hidden = (struct SDL_PrivateVideoData *) SDL_malloc((sizeof(struct SDL_PrivateVideoData)));
2943 }
2944 if ( (device == NULL) || (device->hidden == NULL) )
2945 {
2946 SDL_OutOfMemory();
2947 if ( device )
2948 SDL_free(device);
2949 return NULL;
2950 }
2951 SDL_memset(device->hidden, 0, (sizeof *device->hidden));
2952
2953 /* Set the function pointers */
2954 #ifdef DEBUG_BUILD
2955 printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout);
2956 #endif
2957
2958 /* Initialization/Query functions */
2959 device->VideoInit = os2fslib_VideoInit;
2960 device->ListModes = os2fslib_ListModes;
2961 device->SetVideoMode = os2fslib_SetVideoMode;
2962 device->ToggleFullScreen = os2fslib_ToggleFullScreen;
2963 device->UpdateMouse = os2fslib_UpdateMouse;
2964 device->CreateYUVOverlay = NULL;
2965 device->SetColors = os2fslib_SetColors;
2966 device->UpdateRects = os2fslib_UpdateRects;
2967 device->VideoQuit = os2fslib_VideoQuit;
2968 /* Hardware acceleration functions */
2969 device->AllocHWSurface = os2fslib_AllocHWSurface;
2970 device->CheckHWBlit = NULL;
2971 device->FillHWRect = NULL;
2972 device->SetHWColorKey = NULL;
2973 device->SetHWAlpha = NULL;
2974 device->LockHWSurface = os2fslib_LockHWSurface;
2975 device->UnlockHWSurface = os2fslib_UnlockHWSurface;
2976 device->FlipHWSurface = NULL;
2977 device->FreeHWSurface = os2fslib_FreeHWSurface;
2978 /* Window manager functions */
2979 device->SetCaption = os2fslib_SetCaption;
2980 device->SetIcon = os2fslib_SetIcon;
2981 device->IconifyWindow = os2fslib_IconifyWindow;
2982 device->GrabInput = os2fslib_GrabInput;
2983 device->GetWMInfo = NULL;
2984 /* Cursor manager functions to Windowed mode*/
2985 os2fslib_SetCursorManagementFunctions(device, 1);
2986 /* Event manager functions */
2987 device->InitOSKeymap = os2fslib_InitOSKeymap;
2988 device->PumpEvents = os2fslib_PumpEvents;
2989 /* The function used to dispose of this structure */
2990 device->free = os2fslib_DeleteDevice;
2991
2992 // Make sure we'll be able to use Win* API even if the application
2993 // was linked to be a VIO application!
2994 os2fslib_MorphToPM();
2995
2996 // Now initialize FSLib, and query available video modes!
2997 if (!FSLib_Initialize())
2998 {
2999 // Could not initialize FSLib!
3000 #ifdef DEBUG_BUILD
3001 printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n");
3002 #endif
3003 SDL_SetError("Could not initialize FSLib!");
3004 SDL_free(device->hidden);
3005 SDL_free(device);
3006 return NULL;
3007 }
3008 device->hidden->pAvailableFSLibVideoModes =
3009 FSLib_GetVideoModeList();
3010
3011 return device;
3012 }
3013
3014 VideoBootStrap OS2FSLib_bootstrap = {
3015 "os2fslib", "OS/2 Video Output using FSLib",
3016 os2fslib_Available, os2fslib_CreateDevice
3017 };
3018
3019