Home | History | Annotate | Download | only in photon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 (at) 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 }
    625