src/video/windows/SDL_windowsevents.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 24 Jan 2011 15:46:11 -0800
changeset 5086 c2539ff054c8
parent 5062 e8916fe9cfc8
child 5139 57851a238c8f
permissions -rw-r--r--
Fixed compiling on Windows Mobile SDK 5.0 with Visual Studio 2008
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 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     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #include "SDL_config.h"
    24 
    25 #include "SDL_windowsvideo.h"
    26 #include "SDL_windowsshape.h"
    27 #include "SDL_syswm.h"
    28 #include "SDL_vkeys.h"
    29 #include "../../events/SDL_events_c.h"
    30 #include "../../events/SDL_touch_c.h"
    31 
    32 
    33 
    34 /*#define WMMSG_DEBUG*/
    35 #ifdef WMMSG_DEBUG
    36 #include <stdio.h>	
    37 #include "wmmsg.h"
    38 #endif
    39 
    40 /* Masks for processing the windows KEYDOWN and KEYUP messages */
    41 #define REPEATED_KEYMASK    (1<<30)
    42 #define EXTENDED_KEYMASK    (1<<24)
    43 
    44 #define VK_ENTER    10          /* Keypad Enter ... no VKEY defined? */
    45 
    46 /* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
    47 #ifndef WM_XBUTTONDOWN
    48 #define WM_XBUTTONDOWN 0x020B
    49 #endif
    50 #ifndef WM_XBUTTONUP
    51 #define WM_XBUTTONUP 0x020C
    52 #endif
    53 #ifndef GET_XBUTTON_WPARAM
    54 #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
    55 #endif
    56 #ifndef WM_INPUT
    57 #define WM_INPUT 0x00ff
    58 #endif
    59 #ifndef WM_TOUCH
    60 #define WM_TOUCH 0x0240
    61 #endif
    62 
    63 
    64 static WPARAM
    65 RemapVKEY(WPARAM wParam, LPARAM lParam)
    66 {
    67     int i;
    68     BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF);
    69 
    70     /* Windows remaps alphabetic keys based on current layout.
    71        We try to provide USB scancodes, so undo this mapping.
    72      */
    73     if (wParam >= 'A' && wParam <= 'Z') {
    74         if (scancode != alpha_scancodes[wParam - 'A']) {
    75             for (i = 0; i < SDL_arraysize(alpha_scancodes); ++i) {
    76                 if (scancode == alpha_scancodes[i]) {
    77                     wParam = 'A' + i;
    78                     break;
    79                 }
    80             }
    81         }
    82     }
    83 
    84     /* Keypad keys are a little trickier, we always scan for them.
    85        Keypad arrow keys have the same scancode as normal arrow keys,
    86        except they don't have the extended bit (0x1000000) set.
    87      */
    88     if (!(lParam & 0x1000000)) {
    89         if (wParam == VK_DELETE) {
    90             wParam = VK_DECIMAL;
    91         } else {
    92             for (i = 0; i < SDL_arraysize(keypad_scancodes); ++i) {
    93                 if (scancode == keypad_scancodes[i]) {
    94                     wParam = VK_NUMPAD0 + i;
    95                     break;
    96                 }
    97             }
    98         }
    99     }
   100 
   101     return wParam;
   102 }
   103 
   104 LRESULT CALLBACK
   105 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
   106 {
   107     SDL_WindowData *data;
   108     LRESULT returnCode = -1;
   109 
   110     /* Send a SDL_SYSWMEVENT if the application wants them */
   111     if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
   112         SDL_SysWMmsg wmmsg;
   113 
   114         SDL_VERSION(&wmmsg.version);
   115         wmmsg.subsystem = SDL_SYSWM_WINDOWS;
   116         wmmsg.msg.win.hwnd = hwnd;
   117         wmmsg.msg.win.msg = msg;
   118         wmmsg.msg.win.wParam = wParam;
   119         wmmsg.msg.win.lParam = lParam;
   120         SDL_SendSysWMEvent(&wmmsg);
   121     }
   122 
   123     /* Get the window data for the window */
   124     data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
   125     if (!data) {
   126         return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
   127     }
   128 
   129 #ifdef WMMSG_DEBUG
   130     {		
   131         FILE *log = fopen("wmmsg.txt", "a");		
   132         fprintf(log, "Received windows message: %p ", hwnd);
   133         if (msg > MAX_WMMSG) {
   134             fprintf(log, "%d", msg);
   135         } else {
   136             fprintf(log, "%s", wmtab[msg]);
   137         }
   138         fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
   139         fclose(log);
   140     }
   141 #endif
   142 
   143     if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
   144         return 0;
   145 
   146     switch (msg) {
   147 
   148     case WM_SHOWWINDOW:
   149         {
   150             if (wParam) {
   151                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   152             } else {
   153                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   154             }
   155         }
   156         break;
   157 
   158     case WM_ACTIVATE:
   159         {
   160             BOOL minimized;
   161 
   162             minimized = HIWORD(wParam);
   163             if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
   164                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
   165                 SDL_SendWindowEvent(data->window,
   166                                     SDL_WINDOWEVENT_RESTORED, 0, 0);
   167 #ifndef _WIN32_WCE              /* WinCE misses IsZoomed() */
   168                 if (IsZoomed(hwnd)) {
   169                     SDL_SendWindowEvent(data->window,
   170                                         SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
   171                 }
   172 #endif
   173                 if (SDL_GetKeyboardFocus() != data->window) {
   174                     SDL_SetKeyboardFocus(data->window);
   175                 }
   176                 /*
   177                  * FIXME: Update keyboard state
   178                  */
   179                 WIN_CheckClipboardUpdate(data->videodata);
   180             } else {
   181                 if (SDL_GetKeyboardFocus() == data->window) {
   182                     SDL_SetKeyboardFocus(NULL);
   183                 }
   184                 if (minimized) {
   185                     SDL_SendWindowEvent(data->window,
   186                                         SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   187                 }
   188             }
   189         }
   190         returnCode = 0;
   191         break;
   192 
   193 	case WM_MOUSEMOVE:
   194 #ifdef _WIN32_WCE
   195         /* transform coords for VGA, WVGA... */
   196         {
   197             SDL_VideoData *videodata = data->videodata;
   198             if(videodata->CoordTransform &&
   199                 (videodata->render == RENDER_GAPI || videodata->render == RENDER_RAW))
   200             {
   201                 POINT pt;
   202                 pt.x = LOWORD(lParam);
   203                 pt.y = HIWORD(lParam);
   204                 videodata->CoordTransform(data->window, &pt);
   205                     SDL_SendMouseMotion(data->window, 0, pt.x, pt.y);
   206                 break;
   207             }
   208         }
   209 #endif
   210         SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
   211         break;
   212 
   213     case WM_LBUTTONDOWN:
   214         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
   215         break;
   216 
   217     case WM_LBUTTONUP:
   218         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_LEFT);
   219         break;
   220 
   221     case WM_RBUTTONDOWN:
   222         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_RIGHT);
   223         break;
   224 
   225     case WM_RBUTTONUP:
   226         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_RIGHT);
   227         break;
   228 
   229     case WM_MBUTTONDOWN:
   230         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_MIDDLE);
   231         break;
   232 
   233     case WM_MBUTTONUP:
   234         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_MIDDLE);
   235         break;
   236 
   237     case WM_XBUTTONDOWN:
   238         SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   239         returnCode = TRUE;
   240         break;
   241 
   242     case WM_XBUTTONUP:
   243         SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   244         returnCode = TRUE;
   245         break;
   246 
   247     case WM_MOUSEWHEEL:
   248         {
   249             int motion = (short) HIWORD(wParam);
   250 
   251             SDL_SendMouseWheel(data->window, 0, motion);
   252             break;
   253         }
   254 
   255 #ifdef WM_MOUSELEAVE
   256     /* FIXME: Do we need the SDL 1.2 hack to generate WM_MOUSELEAVE now? */
   257     case WM_MOUSELEAVE:
   258         if (SDL_GetMouseFocus() == data->window) {
   259             SDL_SetMouseFocus(NULL);
   260         }
   261         returnCode = 0;
   262         break;
   263 #endif /* WM_MOUSELEAVE */
   264 
   265     case WM_SYSKEYDOWN:
   266     case WM_KEYDOWN:
   267         {
   268             wParam = RemapVKEY(wParam, lParam);
   269             switch (wParam) {
   270             case VK_CONTROL:
   271                 if (lParam & EXTENDED_KEYMASK)
   272                     wParam = VK_RCONTROL;
   273                 else
   274                     wParam = VK_LCONTROL;
   275                 break;
   276             case VK_SHIFT:
   277                 /* EXTENDED trick doesn't work here */
   278                 {
   279                     Uint8 *state = SDL_GetKeyboardState(NULL);
   280                     if (state[SDL_SCANCODE_LSHIFT] == SDL_RELEASED
   281                         && (GetKeyState(VK_LSHIFT) & 0x8000)) {
   282                         wParam = VK_LSHIFT;
   283                     } else if (state[SDL_SCANCODE_RSHIFT] == SDL_RELEASED
   284                                && (GetKeyState(VK_RSHIFT) & 0x8000)) {
   285                         wParam = VK_RSHIFT;
   286                     } else {
   287                         /* Probably a key repeat */
   288                         wParam = 256;
   289                     }
   290                 }
   291                 break;
   292             case VK_MENU:
   293                 if (lParam & EXTENDED_KEYMASK)
   294                     wParam = VK_RMENU;
   295                 else
   296                     wParam = VK_LMENU;
   297                 break;
   298             case VK_RETURN:
   299                 if (lParam & EXTENDED_KEYMASK)
   300                     wParam = VK_ENTER;
   301                 break;
   302             }
   303             if (wParam < 256) {
   304                 SDL_SendKeyboardKey(SDL_PRESSED,
   305                                     data->videodata->key_layout[wParam]);
   306             }
   307         }
   308         returnCode = 0;
   309         break;
   310 
   311     case WM_SYSKEYUP:
   312     case WM_KEYUP:
   313         {
   314             wParam = RemapVKEY(wParam, lParam);
   315             switch (wParam) {
   316             case VK_CONTROL:
   317                 if (lParam & EXTENDED_KEYMASK)
   318                     wParam = VK_RCONTROL;
   319                 else
   320                     wParam = VK_LCONTROL;
   321                 break;
   322             case VK_SHIFT:
   323                 /* EXTENDED trick doesn't work here */
   324                 {
   325                     Uint8 *state = SDL_GetKeyboardState(NULL);
   326                     if (state[SDL_SCANCODE_LSHIFT] == SDL_PRESSED
   327                         && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
   328                         wParam = VK_LSHIFT;
   329                     } else if (state[SDL_SCANCODE_RSHIFT] == SDL_PRESSED
   330                                && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
   331                         wParam = VK_RSHIFT;
   332                     } else {
   333                         /* Probably a key repeat */
   334                         wParam = 256;
   335                     }
   336                 }
   337                 break;
   338             case VK_MENU:
   339                 if (lParam & EXTENDED_KEYMASK)
   340                     wParam = VK_RMENU;
   341                 else
   342                     wParam = VK_LMENU;
   343                 break;
   344             case VK_RETURN:
   345                 if (lParam & EXTENDED_KEYMASK)
   346                     wParam = VK_ENTER;
   347                 break;
   348             }
   349 
   350             /* Windows only reports keyup for print screen */
   351             if (wParam == VK_SNAPSHOT
   352                 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
   353                 SDL_RELEASED) {
   354                 SDL_SendKeyboardKey(SDL_PRESSED,
   355                                     data->videodata->key_layout[wParam]);
   356             }
   357             if (wParam < 256) {
   358                 SDL_SendKeyboardKey(SDL_RELEASED,
   359                                     data->videodata->key_layout[wParam]);
   360             }
   361         }
   362         returnCode = 0;
   363         break;
   364 
   365     case WM_CHAR:
   366         {
   367             char text[4];
   368 
   369             /* Convert to UTF-8 and send it on... */
   370             if (wParam <= 0x7F) {
   371                 text[0] = (char) wParam;
   372                 text[1] = '\0';
   373             } else if (wParam <= 0x7FF) {
   374                 text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
   375                 text[1] = 0x80 | (char) (wParam & 0x3F);
   376                 text[2] = '\0';
   377             } else {
   378                 text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
   379                 text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
   380                 text[2] = 0x80 | (char) (wParam & 0x3F);
   381                 text[3] = '\0';
   382             }
   383             SDL_SendKeyboardText(text);
   384         }
   385         returnCode = 0;
   386         break;
   387 
   388 #ifdef WM_INPUTLANGCHANGE
   389     case WM_INPUTLANGCHANGE:
   390         {
   391             WIN_UpdateKeymap();
   392         }
   393         returnCode = 1;
   394         break;
   395 #endif /* WM_INPUTLANGCHANGE */
   396 
   397 #ifdef WM_GETMINMAXINFO
   398     case WM_GETMINMAXINFO:
   399         {
   400             MINMAXINFO *info;
   401             RECT size;
   402             int x, y;
   403             int w, h;
   404             int style;
   405             BOOL menu;
   406 
   407             /* If we allow resizing, let the resize happen naturally */
   408             if(SDL_IsShapedWindow(data->window))
   409                 Win32_ResizeWindowShape(data->window);
   410             if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
   411                 returnCode = 0;
   412                 break;
   413             }
   414 
   415             /* Get the current position of our window */
   416             GetWindowRect(hwnd, &size);
   417             x = size.left;
   418             y = size.top;
   419 
   420             /* Calculate current size of our window */
   421             SDL_GetWindowSize(data->window, &w, &h);
   422             size.top = 0;
   423             size.left = 0;
   424             size.bottom = h;
   425             size.right = w;
   426 
   427 
   428             style = GetWindowLong(hwnd, GWL_STYLE);
   429 #ifdef _WIN32_WCE
   430             menu = FALSE;
   431 #else
   432             /* DJM - according to the docs for GetMenu(), the
   433                return value is undefined if hwnd is a child window.
   434                Aparently it's too difficult for MS to check
   435                inside their function, so I have to do it here.
   436              */
   437             menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
   438 #endif
   439             AdjustWindowRectEx(&size, style, menu, 0);
   440             w = size.right - size.left;
   441             h = size.bottom - size.top;
   442 
   443             /* Fix our size to the current size */
   444             info = (MINMAXINFO *) lParam;
   445             info->ptMaxSize.x = w;
   446             info->ptMaxSize.y = h;
   447             info->ptMaxPosition.x = x;
   448             info->ptMaxPosition.y = y;
   449             info->ptMinTrackSize.x = w;
   450             info->ptMinTrackSize.y = h;
   451             info->ptMaxTrackSize.x = w;
   452             info->ptMaxTrackSize.y = h;
   453         }
   454         returnCode = 0;
   455         break;
   456 #endif /* WM_GETMINMAXINFO */
   457 
   458     case WM_WINDOWPOSCHANGED:
   459         {
   460             RECT rect;
   461             int x, y;
   462             int w, h;
   463             Uint32 window_flags;
   464 
   465             if (!GetClientRect(hwnd, &rect) ||
   466                 (rect.right == rect.left && rect.bottom == rect.top)) {
   467                 break;
   468             }
   469             ClientToScreen(hwnd, (LPPOINT) & rect);
   470             ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   471 
   472             window_flags = SDL_GetWindowFlags(data->window);
   473             if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
   474                 (window_flags & SDL_WINDOW_INPUT_FOCUS)) {
   475                 ClipCursor(&rect);
   476             }
   477 
   478             x = rect.left;
   479             y = rect.top;
   480             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
   481 
   482             w = rect.right - rect.left;
   483             h = rect.bottom - rect.top;
   484             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
   485                                 h);
   486         }
   487         break;
   488 
   489     case WM_SETCURSOR:
   490         {
   491             Uint16 hittest;
   492 
   493             hittest = LOWORD(lParam);
   494             if (hittest == HTCLIENT) {
   495                 /* FIXME: Implement the cursor API */
   496                 static HCURSOR cursor;
   497                 if (!cursor) {
   498                     cursor = LoadCursor(NULL, IDC_ARROW);
   499                 }
   500                 SetCursor(cursor);
   501                 returnCode = TRUE;
   502             }
   503         }
   504         break;
   505 
   506         /* We are about to get palette focus! */
   507     case WM_QUERYNEWPALETTE:
   508         {
   509             /*
   510                 WIN_RealizePalette(current_video);
   511                 returnCode = TRUE;
   512              */
   513         }
   514         break;
   515 
   516         /* Another application changed the palette */
   517     case WM_PALETTECHANGED:
   518         {
   519             /*
   520                WIN_PaletteChanged(current_video, (HWND) wParam);
   521              */
   522         }
   523         break;
   524 
   525         /* We were occluded, refresh our display */
   526     case WM_PAINT:
   527         {
   528             RECT rect;
   529             if (GetUpdateRect(hwnd, &rect, FALSE)) {
   530                 ValidateRect(hwnd, &rect);
   531                 SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
   532                                     0, 0);
   533             }
   534         }
   535         returnCode = 0;
   536         break;
   537 
   538         /* We'll do our own drawing, prevent flicker */
   539     case WM_ERASEBKGND:
   540         {
   541         }
   542         return (1);
   543 
   544 #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
   545     case WM_SYSCOMMAND:
   546         {
   547             /* Don't start the screensaver or blank the monitor in fullscreen apps */
   548             if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
   549                 (wParam & 0xFFF0) == SC_MONITORPOWER) {
   550                 if (SDL_GetVideoDevice()->suspend_screensaver) {
   551                     return (0);
   552                 }
   553             }
   554         }
   555         break;
   556 #endif /* System has screensaver support */
   557 
   558     case WM_CLOSE:
   559         {
   560             SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
   561         }
   562         returnCode = 0;
   563         break;
   564 
   565 	case WM_TOUCH:
   566 		{
   567 			UINT i, num_inputs = LOWORD(wParam);
   568 			PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
   569 			if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
   570 				RECT rect;
   571 				float x, y;
   572 
   573 				if (!GetClientRect(hwnd, &rect) ||
   574 				    (rect.right == rect.left && rect.bottom == rect.top)) {
   575 					break;
   576 				}
   577 				ClientToScreen(hwnd, (LPPOINT) & rect);
   578 				ClientToScreen(hwnd, (LPPOINT) & rect + 1);
   579 				rect.top *= 100;
   580 				rect.left *= 100;
   581 				rect.bottom *= 100;
   582 				rect.right *= 100;
   583 
   584 				for (i = 0; i < num_inputs; ++i) {
   585 					PTOUCHINPUT input = &inputs[i];
   586 
   587 					SDL_TouchID touchId = (SDL_TouchID)input->hSource;
   588 					if (!SDL_GetTouch(touchId)) {
   589 						SDL_Touch touch;
   590 
   591 						touch.id = touchId;
   592 						touch.x_min = 0;
   593 						touch.x_max = 1;
   594 						touch.native_xres = touch.x_max - touch.x_min;
   595 						touch.y_min = 0;
   596 						touch.y_max = 1;
   597 						touch.native_yres = touch.y_max - touch.y_min;
   598 						touch.pressure_min = 0;
   599 						touch.pressure_max = 1;
   600 						touch.native_pressureres = touch.pressure_max - touch.pressure_min;
   601 
   602 						if (SDL_AddTouch(&touch, "") < 0) {
   603 							continue;
   604 						}
   605 					}
   606 
   607 					// Get the normalized coordinates for the window
   608 					x = (float)(input->x - rect.left)/(rect.right - rect.left);
   609 					y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
   610 
   611 					if (input->dwFlags & TOUCHEVENTF_DOWN) {
   612 						SDL_SendFingerDown(touchId, input->dwID, SDL_TRUE, x, y, 1);
   613 					}
   614 					if (input->dwFlags & TOUCHEVENTF_MOVE) {
   615 						SDL_SendTouchMotion(touchId, input->dwID, SDL_FALSE, x, y, 1);
   616 					}
   617 					if (input->dwFlags & TOUCHEVENTF_UP) {
   618 						SDL_SendFingerDown(touchId, input->dwID, SDL_FALSE, x, y, 1);
   619 					}
   620 				}
   621 			}
   622 			SDL_stack_free(inputs);
   623 
   624 			data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
   625 			return 0;
   626 		}
   627 		break;
   628 	}
   629 
   630     /* If there's a window proc, assume it's going to handle messages */
   631     if (data->wndproc) {
   632         return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
   633     } else if (returnCode >= 0) {
   634         return returnCode;
   635     } else {
   636         return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
   637     }
   638 }
   639 
   640 void
   641 WIN_PumpEvents(_THIS)
   642 {
   643     MSG msg;
   644     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
   645         TranslateMessage(&msg);
   646         DispatchMessage(&msg);
   647     }
   648 }
   649 
   650 static int app_registered = 0;
   651 LPTSTR SDL_Appname = NULL;
   652 Uint32 SDL_Appstyle = 0;
   653 HINSTANCE SDL_Instance = NULL;
   654 
   655 /* Register the class for this application */
   656 int
   657 SDL_RegisterApp(char *name, Uint32 style, void *hInst)
   658 {
   659     WNDCLASS class;
   660 
   661     /* Only do this once... */
   662     if (app_registered) {
   663         ++app_registered;
   664         return (0);
   665     }
   666     if (!name && !SDL_Appname) {
   667         name = "SDL_app";
   668 #if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
   669         SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
   670 #endif
   671         SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
   672     }
   673 
   674     if (name) {
   675         SDL_Appname = WIN_UTF8ToString(name);
   676         SDL_Appstyle = style;
   677         SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
   678     }
   679 
   680     /* Register the application class */
   681     class.hCursor = NULL;
   682     class.hIcon =
   683         LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
   684                   LR_DEFAULTCOLOR);
   685     class.lpszMenuName = NULL;
   686     class.lpszClassName = SDL_Appname;
   687     class.hbrBackground = NULL;
   688     class.hInstance = SDL_Instance;
   689     class.style = SDL_Appstyle;
   690     class.lpfnWndProc = WIN_WindowProc;
   691     class.cbWndExtra = 0;
   692     class.cbClsExtra = 0;
   693     if (!RegisterClass(&class)) {
   694         SDL_SetError("Couldn't register application class");
   695         return (-1);
   696     }
   697 
   698     app_registered = 1;
   699     return (0);
   700 }
   701 
   702 /* Unregisters the windowclass registered in SDL_RegisterApp above. */
   703 void
   704 SDL_UnregisterApp()
   705 {
   706     WNDCLASS class;
   707 
   708     /* SDL_RegisterApp might not have been called before */
   709     if (!app_registered) {
   710         return;
   711     }
   712     --app_registered;
   713     if (app_registered == 0) {
   714         /* Check for any registered window classes. */
   715         if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
   716             UnregisterClass(SDL_Appname, SDL_Instance);
   717         }
   718         SDL_free(SDL_Appname);
   719         SDL_Appname = NULL;
   720     }
   721 }
   722 
   723 /* vi: set ts=4 sw=4 expandtab: */