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