src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 14 Feb 2004 20:22:21 +0000
changeset 821 30168104389f
parent 769 b8d311d90021
child 886 05c551e5bc64
permissions -rw-r--r--
Date: Sat, 14 Feb 2004 14:52:40 +0200
From: "Mike Gorchak"
Subject: Batch of the QNX6 fixes for the SDL

1. Updated readme.QNX
2. Fixed crashes during intensive window updating under fast machines (got over 200 rectangles for update).
3. Fixed double-buffered fullscreen modes, now it works as needed.
4. Fixed Photon detection algorithm.
5. Fixed HWSURFACE update function.
6. Added SDL_PHOTON_FULLSCREEN_REFRESH environment variable support for control refresh rates under Photon.
7. Added 640x400 fullscreen mode emulation via 640x480 (if videodriver not supports original 640x400 mode of course) shifted by 40 vertical pixels from begin, to center it. It's needed for some old DOS games which ran in doubled 320x200 mode.
8. Added available video ram amount support.
8. Added hardware surface allocation/deallocation support if current videomode and videodriver supports it.
9. Added hardware filling support.
10. Added hardware blits support (simple and colorkeyed).

And I've added to testvidinfo test color-keyed blits benchmark (maybe need to add alpha blits benchmark too ?). Currently Photon not supporting any alpha hardware blittings (all drivers lack of alpha blitting code support, only software alpha blitting exist in photon, which is hundreds times slowest than the SDL's one). So I've not added the alpha support. I suppose new QNX 6.3 will have the hardware alpha support, so when it will be done, I'll add alpha support.
     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 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* Handle the event stream, converting photon events into SDL events */
    29 
    30 #define DISABLE_X11
    31 
    32 #include <stdio.h>
    33 #include <setjmp.h>
    34 #include <sys/time.h>
    35 
    36 #include <Ph.h>
    37 #include <photon/PkKeyDef.h>
    38 
    39 #include "SDL.h"
    40 #include "SDL_syswm.h"
    41 #include "SDL_sysevents.h"
    42 #include "SDL_sysvideo.h"
    43 #include "SDL_events_c.h"
    44 #include "SDL_ph_video.h"
    45 #include "SDL_ph_modes_c.h"
    46 #include "SDL_ph_image_c.h"
    47 #include "SDL_ph_events_c.h"
    48 #include "SDL_phyuv_c.h"
    49 
    50 /* The translation tables from a photon keysym to a SDL keysym */
    51 static SDLKey ODD_keymap[256];
    52 static SDLKey MISC_keymap[0xFF + 1];
    53 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym);
    54 
    55 /* Check to see if this is a repeated key.
    56    (idea shamelessly lifted from GII -- thanks guys! :) */
    57 static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent)
    58 {
    59     PhRect_t *rect = PhGetRects( winEvent );
    60 
    61     int centre_x, centre_y;
    62     int dx, dy;
    63     short abs_x, abs_y;
    64     int posted;
    65 
    66     centre_x = SDL_VideoSurface->w / 2;
    67     centre_y = SDL_VideoSurface->h / 2;
    68 
    69     dx = rect->ul.x - centre_x;
    70     dy = rect->ul.y - centre_y;
    71 
    72     posted = SDL_PrivateMouseMotion( 0, 1, dx, dy );
    73 
    74     /* Move mouse cursor to middle of the window */
    75     PtGetAbsPosition( window, &abs_x, &abs_y );
    76     PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y);
    77 
    78     return (posted);
    79 }
    80 
    81 /* Control which motion flags the window has set, a flags value of -1 sets
    82  * MOTION_BUTTON and MOTION_NOBUTTON */
    83 
    84 static void set_motion_sensitivity(_THIS, unsigned int flags)
    85 {
    86     int rid;
    87     int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
    88     PhRegion_t region;
    89 
    90     if( window )
    91     {
    92         rid = PtWidgetRid(window);
    93         if( rid != 0 && PhRegionQuery(rid, &region, NULL, NULL, 0) == 0 )
    94         {
    95             region.events_sense=(region.events_sense & ~fields)|(flags & fields);
    96             PhRegionChange(Ph_REGION_EV_SENSE, 0, &region, NULL, NULL);
    97         }
    98     }
    99 }
   100 
   101 /* Convert the photon button state value to an SDL value */
   102 static Uint8 ph2sdl_mousebutton(unsigned short button_state)
   103 {
   104     Uint8 mouse_button = 0;
   105 
   106     if (button_state & Ph_BUTTON_SELECT)
   107         mouse_button |= SDL_BUTTON_LEFT;
   108     if (button_state & Ph_BUTTON_MENU)
   109         mouse_button |= SDL_BUTTON_RIGHT;
   110     if (button_state & Ph_BUTTON_ADJUST)
   111         mouse_button |= SDL_BUTTON_MIDDLE;
   112 
   113     return (mouse_button);
   114 }
   115 
   116 static int ph_DispatchEvent(_THIS)
   117 {
   118     int posted;
   119     PhRect_t* rect;
   120     PhPointerEvent_t* pointerEvent;
   121     PhKeyEvent_t* keyEvent;
   122     PhWindowEvent_t* winEvent;
   123     int i, buttons;
   124     SDL_Rect sdlrects[PH_SDL_MAX_RECTS];
   125 	
   126     posted = 0;
   127 	
   128     switch (event->type)
   129     {
   130         case Ph_EV_BOUNDARY:
   131         {
   132             if (event->subtype == Ph_EV_PTR_ENTER)
   133             {
   134                 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   135             }
   136             else if (event->subtype ==Ph_EV_PTR_LEAVE)
   137             {
   138                 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);	
   139             }
   140         }
   141         break;
   142 
   143         case Ph_EV_PTR_MOTION_BUTTON:
   144         case Ph_EV_PTR_MOTION_NOBUTTON:
   145         {
   146             if (SDL_VideoSurface)
   147             {
   148                 pointerEvent = PhGetData(event);
   149                 rect = PhGetRects(event);
   150 
   151                 if (mouse_relative)
   152                 {
   153                     posted = ph_WarpedMotion(this, event);
   154                 }
   155                 else
   156                 {
   157                     posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y);
   158                 }
   159             }
   160         }
   161         break;
   162 
   163         case Ph_EV_BUT_PRESS:
   164         {
   165             pointerEvent = PhGetData( event );
   166             buttons = ph2sdl_mousebutton( pointerEvent->buttons );
   167             if (buttons != 0)
   168             {
   169                 posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0);
   170             }
   171         }
   172         break;
   173 
   174         case Ph_EV_BUT_RELEASE:
   175         {
   176             pointerEvent = PhGetData(event);
   177             buttons = ph2sdl_mousebutton(pointerEvent->buttons);
   178             if (event->subtype == Ph_EV_RELEASE_REAL && buttons != 0)
   179             {
   180                 posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
   181             }
   182             else if(event->subtype == Ph_EV_RELEASE_PHANTOM)
   183             {
   184                 /* If the mouse is outside the window,
   185                  * only a phantom release event is sent, so
   186                  * check if the window doesn't have mouse focus.
   187                  * Not perfect, maybe checking the mouse button
   188                  * state for Ph_EV_BOUNDARY events would be
   189                  * better. */
   190                 if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0)
   191 		{
   192                     posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
   193                 }
   194             }
   195         }
   196         break;
   197 
   198         case Ph_EV_WM:
   199         {
   200             winEvent = PhGetData(event);
   201 
   202             /* losing focus */
   203             if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
   204             {
   205                 set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON);
   206                 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);	
   207             }
   208             /* gaining focus */
   209             else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
   210             {
   211                 set_motion_sensitivity(this, -1);
   212                 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   213             }
   214             /* request quit */
   215             else if (winEvent->event_f==Ph_WM_CLOSE)
   216             {
   217                 posted = SDL_PrivateQuit();
   218             }
   219             /* request hide/unhide */
   220             else if (winEvent->event_f==Ph_WM_HIDE)
   221             {
   222                 if (currently_hided)
   223                 {
   224                    /* got unhide window event                                */
   225                    /* TODO: restore application's palette if in palette mode */
   226                    currently_hided=0;
   227                 }
   228                 else
   229                 {
   230                    /* got hide window event                                  */
   231                    /* TODO: restore original palette if in palette mode      */
   232                    currently_hided=1;
   233                 }
   234             }
   235             /* request to resize */
   236             else if (winEvent->event_f==Ph_WM_RESIZE)
   237             {
   238                 SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1);
   239             }
   240             /* request to move */
   241             else if (winEvent->event_f==Ph_WM_MOVE)
   242             {
   243                 if (current_overlay!=NULL)
   244                 {
   245                    int lockedstate=current_overlay->hwdata->locked;
   246                    int chromastate=current_overlay->hwdata->ischromakey;
   247                    int error;
   248                    SDL_Rect target;
   249 
   250                    current_overlay->hwdata->locked=1;
   251                    target.x=current_overlay->hwdata->CurrentViewPort.pos.x;
   252                    target.y=current_overlay->hwdata->CurrentViewPort.pos.y;
   253                    target.w=current_overlay->hwdata->CurrentViewPort.size.w;
   254                    target.h=current_overlay->hwdata->CurrentViewPort.size.h;
   255                    current_overlay->hwdata->ischromakey=0;
   256                    error=ph_DisplayYUVOverlay(this, current_overlay, &target);
   257                    if (!error)
   258                    {
   259                        current_overlay->hwdata->ischromakey=chromastate;
   260                        current_overlay->hwdata->locked=lockedstate;
   261                    }
   262                 }
   263             }
   264             /* maximize request */
   265             else if (winEvent->event_f==Ph_WM_MAX)
   266             {
   267                 /* window already moved and resized here */
   268                 currently_maximized=1;
   269             }
   270             /* restore request */
   271             else if (winEvent->event_f==Ph_WM_RESTORE)
   272             {
   273                 /* window already moved and resized here */
   274                 currently_maximized=0;
   275             }
   276         }
   277         break;
   278 
   279         /* window has been resized, moved or removed */
   280         case Ph_EV_EXPOSE:
   281         {
   282             if (event->num_rects!=0)
   283             {
   284                 int numrects;
   285 
   286                 if (SDL_VideoSurface)
   287                 {
   288                     rect = PhGetRects(event);
   289                     if (event->num_rects>PH_SDL_MAX_RECTS)
   290                     {
   291                        /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */
   292                        numrects=PH_SDL_MAX_RECTS;
   293                     }
   294 
   295                     for(i=0; i<event->num_rects; i++)
   296                     {
   297                         sdlrects[i].x = rect[i].ul.x;
   298                         sdlrects[i].y = rect[i].ul.y;
   299                         sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1;
   300                         sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1;
   301                     }
   302 
   303                     this->UpdateRects(this, event->num_rects, sdlrects);
   304 
   305                     if (current_overlay!=NULL)
   306                     {
   307                         int lockedstate=current_overlay->hwdata->locked;
   308                         int error;
   309                         SDL_Rect target;
   310 
   311                         current_overlay->hwdata->locked=1;
   312                         target.x=current_overlay->hwdata->CurrentViewPort.pos.x;
   313                         target.y=current_overlay->hwdata->CurrentViewPort.pos.y;
   314                         target.w=current_overlay->hwdata->CurrentViewPort.size.w;
   315                         target.h=current_overlay->hwdata->CurrentViewPort.size.h;
   316                         current_overlay->hwdata->forcedredraw=1;
   317                         error=ph_DisplayYUVOverlay(this, current_overlay, &target);
   318                         if (!error)
   319                         {
   320                             current_overlay->hwdata->forcedredraw=0;
   321                             current_overlay->hwdata->locked=lockedstate;
   322                         }
   323                     }
   324                 }
   325             }
   326         }
   327 	break;
   328 
   329         case Ph_EV_KEY:
   330         {
   331             SDL_keysym keysym;
   332 
   333             posted = 0;
   334 
   335             keyEvent = PhGetData( event );
   336 
   337             if (Pk_KF_Key_Down & keyEvent->key_flags)
   338             {
   339                 /* split the wheel events from real key events */
   340                 if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
   341                 {
   342                    posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0);
   343                    break;
   344                 }
   345                 if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
   346                 {
   347                    posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0);
   348                    break;
   349                 }
   350                 posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym));
   351             }
   352             else /* must be key release */
   353             {
   354                 /* split the wheel events from real key events */
   355                 if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
   356                 {
   357                    posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0);
   358                    break;
   359                 }
   360                 if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid))
   361                 {
   362                    posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0);
   363                    break;
   364                 }
   365                 posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym));
   366             }
   367         }
   368         break;
   369         
   370         case Ph_EV_INFO:
   371         {
   372            if (event->subtype==Ph_OFFSCREEN_INVALID)
   373            {
   374               unsigned long* EvInfoData;
   375 
   376               EvInfoData=(unsigned long*)PhGetData(event);
   377 
   378               switch (*EvInfoData)
   379               {
   380                  case Pg_VIDEO_MODE_SWITCHED:
   381                       {
   382                       }
   383                       break;
   384                  case Pg_ENTERED_DIRECT:
   385                       {
   386                       }
   387                       break;
   388                  case Pg_EXITED_DIRECT:
   389                       {
   390                       }
   391                       break;
   392                  case Pg_DRIVER_STARTED:
   393                       {
   394                       }
   395                       break;
   396               }
   397            }
   398         }
   399         break;
   400     }
   401 
   402     return(posted);
   403 }
   404 
   405 /* perform a blocking read if no events available */
   406 int ph_Pending(_THIS)
   407 {
   408     /* Flush the display connection and look to see if events are queued */
   409     PgFlush();
   410 
   411     while (1)
   412     {
   413         switch(PhEventPeek(event, EVENT_SIZE))
   414         {
   415             case Ph_EVENT_MSG:
   416                  return 1;
   417             case -1:
   418                  SDL_SetError("ph_Pending(): PhEventNext failed.\n");
   419                  return 0;
   420             default:
   421                  return 0;
   422         }
   423     }
   424 
   425     /* Oh well, nothing is ready .. */
   426     return(0);
   427 }
   428 
   429 void ph_PumpEvents(_THIS)
   430 {
   431     /* Flush the display connection and look to see if events are queued */
   432     PgFlush();
   433 
   434     while (ph_Pending(this))
   435     {
   436         PtEventHandler(event);
   437         ph_DispatchEvent(this);
   438     }
   439 }
   440 
   441 void ph_InitKeymap(void)
   442 {
   443     int i;
   444 
   445     /* Odd keys used in international keyboards */
   446     for (i=0; i<SDL_TABLESIZE(ODD_keymap); ++i)
   447     {
   448         ODD_keymap[i] = SDLK_UNKNOWN;
   449     }
   450 
   451     /* Map the miscellaneous keys */
   452     for (i=0; i<SDL_TABLESIZE(MISC_keymap); ++i)
   453     {
   454         MISC_keymap[i] = SDLK_UNKNOWN;
   455     }
   456 
   457     MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE;
   458     MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB;
   459     MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR;
   460     MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN;
   461     MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE;
   462     MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE;
   463     MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE;
   464 
   465     MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0;
   466     MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1;
   467     MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2;
   468     MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3;
   469     MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4;
   470     MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5;
   471     MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6;
   472     MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7;
   473     MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8;
   474     MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9;
   475 
   476     MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
   477     MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
   478     MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
   479     MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS;
   480     MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS;
   481     MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER;
   482     MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS;
   483 
   484     MISC_keymap[Pk_Up&0xFF] = SDLK_UP;
   485     MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN;
   486     MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT;
   487     MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT;
   488     MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT;
   489     MISC_keymap[Pk_Home&0xFF] = SDLK_HOME;
   490     MISC_keymap[Pk_End&0xFF] = SDLK_END;
   491     MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP;
   492     MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN;
   493 
   494     MISC_keymap[Pk_F1&0xFF] = SDLK_F1;
   495     MISC_keymap[Pk_F2&0xFF] = SDLK_F2;
   496     MISC_keymap[Pk_F3&0xFF] = SDLK_F3;
   497     MISC_keymap[Pk_F4&0xFF] = SDLK_F4;
   498     MISC_keymap[Pk_F5&0xFF] = SDLK_F5;
   499     MISC_keymap[Pk_F6&0xFF] = SDLK_F6;
   500     MISC_keymap[Pk_F7&0xFF] = SDLK_F7;
   501     MISC_keymap[Pk_F8&0xFF] = SDLK_F8;
   502     MISC_keymap[Pk_F9&0xFF] = SDLK_F9;
   503     MISC_keymap[Pk_F10&0xFF] = SDLK_F10;
   504     MISC_keymap[Pk_F11&0xFF] = SDLK_F11;
   505     MISC_keymap[Pk_F12&0xFF] = SDLK_F12;
   506     MISC_keymap[Pk_F13&0xFF] = SDLK_F13;
   507     MISC_keymap[Pk_F14&0xFF] = SDLK_F14;
   508     MISC_keymap[Pk_F15&0xFF] = SDLK_F15;
   509 
   510     MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK;
   511     MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
   512     MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
   513     MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT;
   514     MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT;
   515     MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL;
   516     MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL;
   517     MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT;
   518     MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT;
   519     MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA;
   520     MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA;
   521     MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER;
   522     MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER;
   523     MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key    */
   524 
   525     MISC_keymap[Pk_Help&0xFF] = SDLK_HELP;
   526     MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT;
   527     MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK;
   528     MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU;        /* Windows "Menu" key */
   529 
   530     MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER;   /* Right "Windows" */
   531 
   532     /* Left "Windows" key, but it can't be catched by application */
   533     MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER;
   534 }
   535 
   536 static unsigned long cap;
   537 
   538 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
   539 {
   540     /* 'sym' is set to the value of the key with modifiers applied to it.
   541        This member is valid only if Pk_KF_Sym_Valid is set in the key_flags.
   542        We will assume it is valid. */
   543 
   544     /* FIXME: This needs to check whether the cap & scancode is valid */
   545 
   546     cap = key->key_cap;
   547 
   548     switch (cap>>8)
   549     {
   550         case 0x00:  /* Latin 1 */
   551         case 0x01:  /* Latin 2 */
   552         case 0x02:  /* Latin 3 */
   553         case 0x03:  /* Latin 4 */
   554         case 0x04:  /* Katakana */
   555         case 0x05:  /* Arabic */
   556         case 0x06:  /* Cyrillic */
   557         case 0x07:  /* Greek */
   558         case 0x08:  /* Technical */
   559         case 0x0A:  /* Publishing */
   560         case 0x0C:  /* Hebrew */
   561         case 0x0D:  /* Thai */
   562                    keysym->sym = (SDLKey)(cap&0xFF);
   563                    /* Map capital letter syms to lowercase */
   564                    if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   565                        keysym->sym += ('a'-'A');
   566                    break;
   567         case 0xF0:
   568                    keysym->sym = MISC_keymap[cap&0xFF];
   569                    break;
   570         default:
   571                    keysym->sym = SDLK_UNKNOWN;                
   572                    break;
   573     }
   574 
   575     keysym->scancode = key->key_scan;
   576     keysym->unicode = 0;
   577 
   578     if (SDL_TranslateUNICODE)
   579     {
   580         char utf8[MB_CUR_MAX];
   581         int utf8len;
   582         wchar_t unicode;
   583 
   584         switch (keysym->scancode)
   585         {
   586            /* Esc key */
   587            case 0x01: keysym->unicode = 27;
   588                       break;
   589            /* BackSpace key */
   590            case 0x0E: keysym->unicode = 127;
   591                       break;
   592            /* Enter key */
   593            case 0x1C: keysym->unicode = 10;
   594                       break;
   595            default:
   596                       utf8len = PhKeyToMb(utf8, key);
   597                       if (utf8len > 0)
   598                       {
   599                          utf8len = mbtowc(&unicode, utf8, utf8len);
   600                          if (utf8len > 0)
   601                          {
   602                              keysym->unicode = unicode;
   603                          }
   604                       }
   605                       break;
   606         }
   607 
   608     }
   609 
   610     return (keysym);
   611 }
   612 
   613 void ph_InitOSKeymap(_THIS)
   614 {
   615     ph_InitKeymap();
   616 }