src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 17 Apr 2006 06:47:23 +0000
changeset 1643 51038e80ae59
parent 1482 141528317f4f
child 1662 782fd950bd46
child 1895 c121d94672cb
child 4159 a1b03ba2fcd0
permissions -rw-r--r--
More general fix for bug #189

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