src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1643 51038e80ae59
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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