src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 20 Feb 2002 01:05:51 +0000
changeset 283 3d8b6b9f1e18
parent 266 c6abdda2f666
child 297 f6ffac90895c
permissions -rw-r--r--
Date: Mon, 18 Feb 2002 16:46:59 +1200
From: Julian Kinraid <jkinraid@clear.net.nz>
Subject: Patches for photon port of SDL

Hi,

A couple more patches for photon and the nto audio. Adds mouse grabbing
support, fixed cursor images, unicode keyboard events (though no unicode
data on kye release, is that a problem?), hopefully fixing some audio
lag problems, and a few other fixes.

Thanks,
Julian Kinraid
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* Handle the event stream, converting photon events into SDL events */
    29 
    30 #define DISABLE_X11
    31 
    32 #include <Ph.h>
    33 #include <stdio.h>
    34 #include <setjmp.h>
    35 #include <photon/PkKeyDef.h>
    36 #include <sys/time.h>
    37 
    38 #include "SDL.h"
    39 #include "SDL_syswm.h"
    40 #include "SDL_sysevents.h"
    41 #include "SDL_sysvideo.h"
    42 #include "SDL_events_c.h"
    43 #include "SDL_ph_video.h"
    44 #include "SDL_ph_modes_c.h"
    45 #include "SDL_ph_image_c.h"
    46 #include "SDL_ph_events_c.h"
    47 
    48 
    49 /* The translation tables from a photon keysym to a SDL keysym */
    50 static SDLKey ODD_keymap[256];
    51 static SDLKey MISC_keymap[0xFF + 1];
    52 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym);
    53 
    54 /* Check to see if this is a repeated key.
    55    (idea shamelessly lifted from GII -- thanks guys! :)
    56  */
    57 
    58 #if 0
    59 static int ph_KeyRepeat(_THIS, PhKeyEvent_t* keyevent)
    60 {
    61 //	PhEvent_t* peekevent;
    62 	PhKeyEvent_t* keyEvent;
    63 	int repeated;
    64 
    65 	repeated = 0;
    66 	switch (PhEventPeek( peekevent, EVENT_SIZE ))
    67 	{
    68 		case Ph_EVENT_MSG: {
    69 			if(peekevent->type == Ph_EV_KEY)
    70 			{
    71 				keyEvent = PhGetData( peekevent );
    72 				if ( !(Pk_KF_Key_Down & keyEvent->key_flags) &&
    73 					(keyEvent->key_cap == keyevent->key_cap) &&
    74 					(peekevent->timestamp == event->timestamp)	
    75 				) {
    76 					repeated = 1;
    77 					 //PhEventNext( peekevent, EVENT_SIZE );  
    78 				}				
    79 			}
    80 		}
    81 		break;
    82 
    83 		case -1: {
    84 			perror( "PhEventPeek failed" );
    85 		}
    86 		break;
    87 
    88 		default: // no events pending
    89 	}
    90 	return(repeated);
    91 }
    92 #endif
    93 
    94 static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent)
    95 {
    96 	PhPointerEvent_t *pointer = PhGetData( winEvent );
    97 	PhRect_t *rect = PhGetRects( winEvent );
    98 
    99 	int centre_x, centre_y;
   100 	int dx, dy, abs_x, abs_y;
   101 	int posted;
   102 
   103 	centre_x = SDL_VideoSurface->w / 2;
   104 	centre_y = SDL_VideoSurface->h / 2;
   105 
   106 	dx = rect->ul.x - centre_x;
   107 	dy = rect->ul.y - centre_y;
   108 
   109 	posted = SDL_PrivateMouseMotion( 0, 1, dx, dy );
   110 
   111 	/* Move mouse cursor to middle of the window */
   112 	PtGetAbsPosition( window, &abs_x, &abs_y );
   113 	PhMoveCursorAbs( PhInputGroup(NULL),
   114 			abs_x + centre_x,
   115 			abs_y + centre_y );
   116 
   117 	return(posted);
   118 }
   119 
   120 /* Control which motion flags the window has set, a flags value of -1 sets
   121  * MOTION_BUTTON and MOTION_NOBUTTON */
   122 
   123 static void set_motion_sensitivity(_THIS, unsigned int flags)
   124 {
   125 	int rid, fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
   126 	PhRegion_t region;
   127 
   128 	if( window )
   129 	{
   130 		rid = PtWidgetRid( window );
   131 		if( rid != 0 && PhRegionQuery( rid, &region, NULL, NULL, 0 ) == 0 )
   132 		{
   133 			region.events_sense = ( region.events_sense & ~fields ) |
   134 				( flags & fields );
   135 			PhRegionChange( Ph_REGION_EV_SENSE, 0, &region,
   136 					NULL, NULL );
   137 		}
   138 	}
   139 }
   140 
   141 /* Convert the photon button state value to an SDL value */
   142 static Uint8 ph2sdl_mousebutton( unsigned short button_state )
   143 {
   144 	Uint8 mouse_button = 0;
   145 
   146 	if( button_state & Ph_BUTTON_SELECT )
   147 			mouse_button |= SDL_BUTTON_LEFT;
   148 	if( button_state & Ph_BUTTON_MENU )
   149 			mouse_button |= SDL_BUTTON_RIGHT;
   150 	if( button_state & Ph_BUTTON_ADJUST )
   151 			mouse_button |= SDL_BUTTON_MIDDLE;
   152 
   153 	return( mouse_button );
   154 }
   155 
   156 static int ph_DispatchEvent(_THIS)
   157 {
   158 	int posted;
   159 	PhRect_t* rect;
   160 	PhPointerEvent_t* pointerEvent;
   161 	PhKeyEvent_t* keyEvent;
   162 	PhWindowEvent_t* winEvent;
   163 	int i, buttons;
   164 	SDL_Rect sdlrects[50]; 
   165 	
   166 	posted = 0;
   167 	
   168 	switch (event->type) {
   169 		case Ph_EV_BOUNDARY:
   170 		{
   171 			if (event->subtype == Ph_EV_PTR_ENTER)
   172 				posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   173 			else if (event->subtype ==Ph_EV_PTR_LEAVE)
   174 				posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);	
   175 		}
   176 		break;
   177 
   178 		case Ph_EV_PTR_MOTION_BUTTON:
   179 		case Ph_EV_PTR_MOTION_NOBUTTON:
   180 		{
   181 			if ( SDL_VideoSurface ) {
   182 				pointerEvent = PhGetData( event );
   183 				rect = PhGetRects( event );
   184 				if( mouse_relative )
   185 				{
   186 					posted = ph_WarpedMotion(this, event);
   187 				}
   188 				else
   189 					posted = SDL_PrivateMouseMotion(0, 0,
   190 							rect->ul.x, rect->ul.y);
   191 			}
   192 		}
   193 		break;
   194 
   195 		case Ph_EV_BUT_PRESS:
   196 		{
   197 			pointerEvent = PhGetData( event );
   198 			buttons = ph2sdl_mousebutton( pointerEvent->buttons );
   199 			if( buttons != 0 )
   200 			posted = SDL_PrivateMouseButton( SDL_PRESSED, buttons,
   201 					0, 0 );
   202 		}
   203 		break;
   204 
   205 		case Ph_EV_BUT_RELEASE:
   206 		{
   207 			pointerEvent = PhGetData(event);
   208 			buttons = ph2sdl_mousebutton(pointerEvent->buttons);
   209 			if( event->subtype == Ph_EV_RELEASE_REAL && 
   210 					buttons != 0 )
   211 			{
   212 				posted = SDL_PrivateMouseButton( SDL_RELEASED,
   213 						buttons, 0, 0 );
   214 			}
   215 			else if( event->subtype == Ph_EV_RELEASE_PHANTOM )
   216 			{
   217 				/* If the mouse is outside the window,
   218 				 * only a phantom release event is sent, so
   219 				 * check if the window doesn't have mouse focus.
   220 				 * Not perfect, maybe checking the mouse button
   221 				 * state for Ph_EV_BOUNDARY events would be
   222 				 * better. */
   223 				if( ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) == 0 )
   224 				{
   225 					posted = SDL_PrivateMouseButton( SDL_RELEASED,
   226 						buttons, 0, 0 );
   227 				}
   228 			}
   229 		}
   230 		break;
   231 
   232 		case Ph_EV_WM:
   233 		{
   234 			winEvent = PhGetData( event );
   235 			
   236 			/* losing focus */
   237 			if ((winEvent->event_f==Ph_WM_FOCUS)&&
   238 				(winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
   239 			{
   240 				set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON);
   241 				posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);	
   242 
   243 				/* Queue leaving fullscreen mode */
   244 				switch_waiting = 0x01;
   245 				switch_time = SDL_GetTicks() + 200;
   246 			}
   247 
   248 			/* gaining focus */
   249 			else if ((winEvent->event_f==Ph_WM_FOCUS)&&
   250 					(winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
   251 			{
   252 				set_motion_sensitivity(this, -1);
   253 				posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   254 #if 0
   255 				/* Queue entry into fullscreen mode */
   256 				switch_waiting = 0x01 | SDL_FULLSCREEN;
   257 				switch_time = SDL_GetTicks() + 1500;
   258 #endif
   259 			}
   260 
   261 			/* request to quit */
   262 			else if (winEvent->event_f==Ph_WM_CLOSE)
   263 			{
   264 				posted = SDL_PrivateQuit();
   265 			}
   266 			else if (winEvent->event_f==Ph_WM_RESIZE)
   267 			{
   268 				PhDim_t *size;
   269 
   270 				PtGetResource( window, Pt_ARG_DIM, &size, 0 );
   271 				SDL_PrivateResize(size->w,size->h);
   272 			}
   273 		}
   274 		break;
   275 		
   276 		/* window has been resized, moved or removed */
   277 		case Ph_EV_EXPOSE:
   278 		{
   279 			if (SDL_VideoSurface)
   280 			{
   281 				rect = PhGetRects( event );
   282 
   283 				//PgSetClipping(1, rect );
   284 				for(i=0;i<event->num_rects;i++)
   285 				{
   286 					sdlrects[i].x = rect[i].ul.x;
   287 					sdlrects[i].y = rect[i].ul.y;
   288 					sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1;
   289 					sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1;
   290 				}
   291 
   292 				this->UpdateRects(this, event->num_rects, sdlrects);
   293 
   294 			}
   295 		}
   296 		break;
   297 
   298 		case Ph_EV_KEY:
   299 		{
   300 	
   301 			SDL_keysym keysym;
   302 			
   303 			posted = 0;
   304 			
   305 			keyEvent = PhGetData( event );
   306 
   307 			if (Pk_KF_Key_Down & keyEvent->key_flags)
   308 			{
   309 				
   310 				posted = SDL_PrivateKeyboard(SDL_PRESSED,
   311                 			ph_TranslateKey( keyEvent, &keysym));
   312 			}
   313 			else /* must be key release */
   314  			{
   315  				/* Ignore repeated key release events */
   316 				/*if (! Pk_KF_Key_Repeat & keyEvent->key_flags )*/
   317 				
   318 					posted = SDL_PrivateKeyboard(SDL_RELEASED,
   319         					ph_TranslateKey( keyEvent, &keysym));
   320 				/*}*/
   321 			}
   322 		}
   323 		break;
   324 	}
   325 	
   326 		
   327 	
   328 	return(posted);
   329 }
   330 
   331 /* perform a blocking read if no events available */
   332 int ph_Pending(_THIS)
   333 {
   334 	/* Flush the display connection and look to see if events are queued */
   335 	PgFlush();
   336 
   337      while( 1 )
   338       {   //note this is a non-blocking call
   339           switch( PhEventPeek( event, EVENT_SIZE ) )
   340            {
   341               case Ph_EVENT_MSG:
   342                  
   343                  return 1;
   344                  break;
   345               case -1:
   346                  perror( "PhEventNext failed" );
   347                  break;
   348               default:
   349              	  
   350                 return 0;
   351        }
   352    }
   353 
   354 	/* Oh well, nothing is ready .. */
   355 	return(0);
   356 }
   357 
   358 /*
   359 SAMPLE EVENT PUMP
   360 =================
   361 static void update( int block ){
   362 
   363     int ch,fl;
   364     PhKeyEvent_t *key;
   365 
   366     for( ;; ){
   367 
   368         if( block ){
   369             do{
   370                 fl=PhEventNext( event,EVENT_SIZE );
   371             }while( fl!=Ph_EVENT_MSG );
   372             block=0;
   373         }else{
   374             do{
   375                 fl=PhEventPeek( event,EVENT_SIZE );
   376                 if( !fl ) return;
   377             }while( fl!=Ph_EVENT_MSG );
   378         }
   379 
   380         switch( event->type ){
   381         case Ph_EV_KEY:
   382             key=PhGetData( event );
   383             ch=key->key_cap;    // & 127;
   384             fl=key->key_flags;
   385             if( ch<32 || ch>127 ) break;
   386             if( fl & Pk_KF_Key_Down ){
   387                 if( !(fl & Pk_KF_Key_Repeat) ){
   388                     if( queput-queget<QUE_SIZE ) keyque[ queput++ & QUE_MASK ]=ch;
   389                     keyMatrix[ch]=1;
   390                 }
   391             }else{
   392                 keyMatrix[ch]=0;
   393             }
   394             break;
   395         default:
   396             PtEventHandler( event );
   397         }
   398     }
   399 }
   400 */
   401 
   402 void ph_PumpEvents(_THIS)
   403 {
   404 	int pending;
   405 
   406 	/* Keep processing pending events */
   407 	pending = 0;
   408 	while ( ph_Pending(this) ) {
   409 		ph_DispatchEvent(this);
   410 		++pending;
   411 	}
   412 	if ( switch_waiting ) {
   413 		Uint32 now;
   414 
   415 		now  = SDL_GetTicks();
   416 #if 0
   417 		if ( pending || !SDL_VideoSurface ) {
   418 			/* Try again later... */
   419 			if ( switch_waiting & SDL_FULLSCREEN ) {
   420 				switch_time = now + 1500;
   421 			} else {
   422 				switch_time = now + 200;
   423 			}
   424 		} else if ( now >= switch_time ) {
   425 			Uint32 go_fullscreen;
   426 
   427 			go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   428 			switch_waiting = 0;
   429 			if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
   430 				if ( go_fullscreen ) {
   431 					ph_EnterFullScreen(this);
   432 				} else {
   433 					ph_LeaveFullScreen(this);
   434 				}
   435 			}
   436 			/* Handle focus in/out when grabbed */
   437 /*
   438 			if ( go_fullscreen ) {
   439 				ph_GrabInputNoLock(this, this->input_grab);
   440 			} else {
   441 				ph_GrabInputNoLock(this, SDL_GRAB_OFF);
   442 			}
   443 */
   444 		}
   445 #endif
   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_TABLESIZE(ODD_keymap); ++i )
   455 		ODD_keymap[i] = SDLK_UNKNOWN;
   456 
   457 	/* Map the miscellaneous keys */
   458 	for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i )
   459 		MISC_keymap[i] = SDLK_UNKNOWN;
   460 
   461 	MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE;
   462 	MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB;
   463 	MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR;
   464 	MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN;
   465 	MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE;
   466 	MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE;
   467 	MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE;
   468 
   469 	MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0;
   470 	MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1;
   471 	MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2;
   472 	MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3;
   473 	MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4;
   474 	MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5;
   475 	MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6;
   476 	MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7;
   477 	MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8;
   478 	MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9;
   479 
   480 	MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
   481 	MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
   482 	MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
   483 	MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS;
   484 	MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS;
   485 	MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER;
   486 	MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS;
   487 
   488 	MISC_keymap[Pk_Up&0xFF] = SDLK_UP;
   489 	MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN;
   490 	MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT;
   491 	MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT;
   492 	MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT;
   493 	MISC_keymap[Pk_Home&0xFF] = SDLK_HOME;
   494 	MISC_keymap[Pk_End&0xFF] = SDLK_END;
   495 	MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP;
   496 	MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN;
   497 
   498 	MISC_keymap[Pk_F1&0xFF] = SDLK_F1;
   499 	MISC_keymap[Pk_F2&0xFF] = SDLK_F2;
   500 	MISC_keymap[Pk_F3&0xFF] = SDLK_F3;
   501 	MISC_keymap[Pk_F4&0xFF] = SDLK_F4;
   502 	MISC_keymap[Pk_F5&0xFF] = SDLK_F5;
   503 	MISC_keymap[Pk_F6&0xFF] = SDLK_F6;
   504 	MISC_keymap[Pk_F7&0xFF] = SDLK_F7;
   505 	MISC_keymap[Pk_F8&0xFF] = SDLK_F8;
   506 	MISC_keymap[Pk_F9&0xFF] = SDLK_F9;
   507 	MISC_keymap[Pk_F10&0xFF] = SDLK_F10;
   508 	MISC_keymap[Pk_F11&0xFF] = SDLK_F11;
   509 	MISC_keymap[Pk_F12&0xFF] = SDLK_F12;
   510 	MISC_keymap[Pk_F13&0xFF] = SDLK_F13;
   511 	MISC_keymap[Pk_F14&0xFF] = SDLK_F14;
   512 	MISC_keymap[Pk_F15&0xFF] = SDLK_F15;
   513 
   514 	MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK;
   515 	MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
   516 	MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
   517 	MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT;
   518 	MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT;
   519 	MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL;
   520 	MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL;
   521 	MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT;
   522 	MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT;
   523 	MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA;
   524 	MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA;
   525 	MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
   526 	MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
   527 	MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
   528 
   529 	MISC_keymap[Pk_Help&0xFF] = SDLK_HELP;
   530 	MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT;
   531 //	MISC_keymap[Pk_Sys_Req] = SDLK_SYSREQ;
   532 	MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK;
   533 	MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU;
   534 	MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   535 }
   536 
   537 static unsigned long cap;
   538 
   539 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
   540 {
   541 /*	
   542 	'sym' is set to the value of the key with modifiers applied to it. 
   543 	This member is valid only if Pk_KF_Sym_Valid is set in the key_flags.
   544 	We will assume it is valid.
   545 */
   546 	/* FIXME: This needs to check whether the cap & scancode is valid */
   547 	cap = key->key_cap;
   548 	switch (cap>>8) {
   549             case 0x00:  /* Latin 1 */
   550             case 0x01:  /* Latin 2 */
   551             case 0x02:  /* Latin 3 */
   552             case 0x03:  /* Latin 4 */
   553             case 0x04:  /* Katakana */
   554             case 0x05:  /* Arabic */
   555             case 0x06:  /* Cyrillic */
   556             case 0x07:  /* Greek */
   557             case 0x08:  /* Technical */
   558             case 0x0A:  /* Publishing */
   559             case 0x0C:  /* Hebrew */
   560             case 0x0D:  /* Thai */
   561                 keysym->sym = (SDLKey)(cap&0xFF);
   562                 /* Map capital letter syms to lowercase */
   563                 if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   564                     keysym->sym += ('a'-'A');
   565                 break;
   566 //            case 0xFE:
   567 //                keysym->sym = ODD_keymap[sym&0xFF];
   568 //                break;
   569             case 0xF0:
   570                 keysym->sym = MISC_keymap[cap&0xFF];
   571                 break;
   572             default:
   573 /*                fprintf(stderr,"Photon: Unknown key_cap, cap = 0x%.4x\n", (unsigned int)cap); */
   574 		keysym->sym = SDLK_UNKNOWN;                
   575                 break;
   576 	}
   577 	keysym->scancode = key->key_scan;
   578 	keysym->unicode = 0;
   579 	if( SDL_TranslateUNICODE )
   580 	{
   581 		char utf8[MB_CUR_MAX];
   582 		int utf8len;
   583 		wchar_t unicode;
   584 
   585 		utf8len = PhKeyToMb( utf8, key );
   586 		if( utf8len > 0 )
   587 		{
   588 			utf8len = mbtowc( &unicode, utf8, utf8len );
   589 			if( utf8len > 0)
   590 				keysym->unicode = unicode;
   591 		}
   592 	}
   593 
   594 	return (keysym);
   595 }
   596 
   597 void ph_InitOSKeymap(_THIS)
   598 {
   599 	ph_InitKeymap();
   600 }
   601