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