00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <queue>
00021 #include <SDL.h>
00022 #include <SDL_thread.h>
00023
00024 #include "ctype.h"
00025
00026 #include "../events.h"
00027 #include "../stack.h"
00028 #include "../basegfx.h"
00029 #include "../global.h"
00030
00031 #include "../errors.h"
00032 #include "../util/messaginghub.h"
00033 #include "graphicsqueue.h"
00034
00035 volatile tmousesettings mouseparams;
00036
00037 SDL_mutex* keyboardmutex = NULL;
00038 SDL_mutex* eventHandlingMutex = NULL;
00039 SDL_mutex* eventQueueMutex = NULL;
00040 SDL_mutex* graphicsQueueMutex = NULL;
00041
00042 queue<tkey> keybuffer_sym;
00043 queue<Uint32> keybuffer_prnt;
00044 queue<SDL_Event> eventQueue;
00045 bool _queueEvents = true;
00046 bool _fillLegacyEventStructures = false;
00047
00048 volatile bool eventThreadRunning = false;
00049
00050
00051 std::list<GraphicsQueueOperation*> graphicsQueue;
00052
00053 int exitprogram = 0;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 bool redrawScreen = false;
00064
00065 const bool trueflag = true;
00066
00067 const bool* mouseUpdateFlag = &trueflag;
00068
00069 void setMouseUpdateFlag( const bool* flag )
00070 {
00071 mouseUpdateFlag = flag;
00072 }
00073
00074
00075 void mousevisible( int an)
00076 {}
00077
00078
00079 int getmousestatus ()
00080 {
00081 return 2;
00082 }
00083
00084 int mouseTranslate ( int m)
00085 {
00086
00087 const int mousetranslate[3] = {
00088 0, 2,1
00089 } ;
00090
00091 if ( m >= 3 )
00092 return m;
00093 else
00094 return mousetranslate[m];
00095 }
00096
00097
00098
00099 void setmouseposition ( int x, int y )
00100 {}
00101
00102
00103
00104 void setnewmousepointer ( void* picture, int hotspotx, int hotspoty )
00105 {}
00106
00107
00108 int mouseinrect ( int x1, int y1, int x2, int y2 )
00109 {
00110 if ( mouseparams.x >= x1 && mouseparams.y >= y1 && mouseparams.x <= x2 && mouseparams.y <= y2 )
00111 return 1;
00112 else
00113 return 0;
00114 }
00115
00116 int mouseinrect ( const tmouserect* rect )
00117 {
00118 if ( mouseparams.x >= rect->x1 && mouseparams.y >= rect->y1 && mouseparams.x <= rect->x2 && mouseparams.y <= rect->y2 )
00119 return 1;
00120 else
00121 return 0;
00122 }
00123
00124
00125
00126 tmouserect tmouserect :: operator+ ( const tmouserect& b ) const
00127 {
00128 tmouserect c;
00129 c.x1 = x1 + b.x1;
00130 c.y1 = y1 + b.y1;
00131 c.x2 = x2 + b.x2;
00132 c.y2 = y2 + b.y2;
00133 return c;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 int keypress( void )
00147 {
00148 int result = 0;
00149 int r = SDL_mutexP ( keyboardmutex );
00150 if ( !r ) {
00151 result = !keybuffer_sym.empty ( );
00152 r = SDL_mutexV ( keyboardmutex );
00153 }
00154 return result;
00155 }
00156
00157 void getkeysyms ( tkey* keysym, int* keyprnt )
00158 {
00159 int found = 0;
00160 do {
00161 int r = SDL_mutexP ( keyboardmutex );
00162 if ( !r ) {
00163 if ( !keybuffer_prnt.empty() ) {
00164 *keysym = keybuffer_sym.front();
00165 *keyprnt = keybuffer_prnt.front();
00166 keybuffer_sym.pop();
00167 keybuffer_prnt.pop();
00168 found++;
00169 }
00170 r = SDL_mutexV ( keyboardmutex );
00171 }
00172 if (!found ) {
00173 int t = ticker;
00174 while ( t + 5 > ticker )
00175 releasetimeslice();
00176 }
00177 } while ( !found );
00178 }
00179
00180
00181 char skeypress(tkey keynr)
00182 {
00183 Uint8 *keystate = SDL_GetKeyState ( NULL );
00184 return keystate[ keynr ];
00185 }
00186
00187 bool isKeyPressed(SDLKey key)
00188 {
00189 Uint8 *keystate = SDL_GetKeyState ( NULL );
00190 return keystate[ key ];
00191 }
00192
00193
00194
00195 void wait(void)
00196 {}
00197
00198
00199
00200 tkey char2key(int c )
00201 {
00202 if ( c < 128 )
00203 return tolower(c);
00204 else
00205 return ct_invvalue;
00206 }
00207
00208
00209 int releasetimeslice( void )
00210 {
00211 SDL_Delay(10);
00212 if ( redrawScreen ) {
00213 redrawScreen = false;
00214 copy2screen();
00215 }
00216 return 0;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 volatile int ticker = 0;
00235
00236 void ndelay(int time)
00237 {
00238 long l;
00239
00240 l = ticker;
00241 do {
00242 releasetimeslice();
00243 } while (ticker - l > time);
00244 }
00245
00246
00247 int tticker = 0;
00248
00249 void starttimer(void)
00250 {
00251 tticker = ticker;
00252 }
00253
00254 char time_elapsed(int time)
00255 {
00256 if (tticker + time <= ticker) return 1;
00257 else return 0;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 #include <iostream>
00269
00270 volatile int closeEventThread = 0;
00271
00272 const int keyTranslationNum = 7;
00273 int keyTranslation[keyTranslationNum][2] = { { 228, 132 },
00274 { 246, 148 },
00275 { 252, 129 },
00276 { 196, 142 },
00277 { 214, 153 },
00278 { 220, 154 },
00279 { 223, 225 } };
00280
00281
00282 EventHandlingMutex::EventHandlingMutex()
00283 {
00284 SDL_mutexP ( eventHandlingMutex );
00285 }
00286
00287 EventHandlingMutex::~EventHandlingMutex()
00288 {
00289 SDL_mutexV ( eventHandlingMutex );
00290 }
00291
00292
00293 int processEvents ( )
00294 {
00295 EventHandlingMutex ehm;
00296
00297 SDL_Event event;
00298 int result;
00299 if ( SDL_PollEvent ( &event ) == 1) {
00300 if ( _fillLegacyEventStructures ) {
00301 switch ( event.type ) {
00302 case SDL_MOUSEBUTTONUP:
00303 case SDL_MOUSEBUTTONDOWN:
00304 {
00305 int taste = mouseTranslate(event.button.button - 1);
00306 int state = event.button.type == SDL_MOUSEBUTTONDOWN;
00307 if ( state )
00308 mouseparams.taste |= (1 << taste);
00309 else
00310 mouseparams.taste &= ~(1 << taste);
00311 mouseparams.x = event.button.x;
00312 mouseparams.y = event.button.y;
00313 }
00314 break;
00315
00316 case SDL_MOUSEMOTION:
00317 {
00318 mouseparams.x = event.motion.x;
00319 mouseparams.y = event.motion.y;
00320 mouseparams.x1 = event.motion.x;
00321 mouseparams.y1 = event.motion.y;
00322 mouseparams.taste = 0;
00323 for ( int i = 0; i < 3; i++ )
00324 if ( event.motion.state & (1 << i) )
00325 mouseparams.taste |= 1 << mouseTranslate(i);
00326 }
00327 break;
00328 case SDL_KEYDOWN:
00329 {
00330 int r = SDL_mutexP ( keyboardmutex );
00331 if ( !r ) {
00332 tkey key = event.key.keysym.sym;
00333 if ( event.key.keysym.mod & KMOD_ALT )
00334 key |= ct_altp;
00335 if ( event.key.keysym.mod & KMOD_CTRL )
00336 key |= ct_stp;
00337 if ( event.key.keysym.mod & KMOD_SHIFT )
00338 key |= ct_shp;
00339 keybuffer_sym.push ( key );
00340
00341 int newsym = event.key.keysym.unicode;
00342 for ( int i = 0; i < keyTranslationNum; i++ )
00343 if ( event.key.keysym.unicode == keyTranslation[i][0] )
00344 newsym = keyTranslation[i][1];
00345 keybuffer_prnt.push ( newsym );
00346 r = SDL_mutexV ( keyboardmutex );
00347 }
00348 }
00349 break;
00350 case SDL_KEYUP:
00351 {}
00352 break;
00353
00354 case SDL_QUIT:
00355 exitprogram = 1;
00356 break;
00357 #ifdef _WIN32_
00358 case SDL_ACTIVEEVENT:
00359 redrawScreen = true;
00360 break;
00361 #endif
00362 }
00363 } else {
00364 #ifdef _WIN32_
00365 if ( event.type == SDL_ACTIVEEVENT ) {
00366 queueOperation( new UpdateRectOp( SDL_GetVideoSurface(), 0,0,0,0), false, true );
00367 }
00368 #endif
00369
00370 }
00371 result = 1;
00372 if ( _queueEvents ) {
00373 SDL_mutexP( eventQueueMutex );
00374 eventQueue.push ( event );
00375 SDL_mutexV( eventQueueMutex );
00376 }
00377
00378
00379 } else
00380 result = 0;
00381
00382 return result;
00383 }
00384
00385 #if defined(_WIN32_) || defined(__APPLE__)
00386 #define FirstThreadEvents 1
00387 #endif
00388
00389 bool syncGraphics = true;
00390
00391
00392 SigC::Signal1<void,const SDL_Surface*> postScreenUpdate;
00393
00394 void queueOperation( GraphicsQueueOperation* gqo, bool wait, bool forceAsync )
00395 {
00396 if ( !eventThreadRunning ) {
00397 gqo->execute();
00398 delete gqo;
00399 return;
00400 }
00401
00402 SDL_mutexP( graphicsQueueMutex );
00403 graphicsQueue.push_back( gqo );
00404 SDL_mutexV( graphicsQueueMutex );
00405
00406 if ( forceAsync )
00407 return;
00408
00409 if ( syncGraphics || wait ) {
00410 bool finished = false;
00411 do {
00412 SDL_Delay(10);
00413 SDL_mutexP( graphicsQueueMutex );
00414 finished = graphicsQueue.empty();
00415 SDL_mutexV( graphicsQueueMutex );
00416 } while (!finished);
00417 }
00418 }
00419
00420
00421 void UpdateRectOp::execute()
00422 {
00423 if ( *mouseUpdateFlag )
00424 SDL_ShowCursor( 0 );
00425
00426 SDL_UpdateRect( screen, x,y,w,h);
00427 postScreenUpdate( screen );
00428
00429 if ( *mouseUpdateFlag )
00430 SDL_ShowCursor( 1 );
00431 };
00432
00433
00434 UpdateRectsOp::UpdateRectsOp( SDL_Surface *screen, int numrects, SDL_Rect *rects)
00435 {
00436 this->numrects = numrects;
00437 this->rects = new SDL_Rect[numrects];
00438 for ( int i = 0; i< numrects; ++i )
00439 this->rects[i] = rects[i];
00440 this->screen = screen;
00441 };
00442
00443 UpdateRectsOp::~UpdateRectsOp()
00444 {
00445 delete[] rects;
00446 }
00447
00448 void UpdateRectsOp::execute()
00449 {
00450 if ( *mouseUpdateFlag )
00451 SDL_ShowCursor( 0 );
00452
00453 SDL_UpdateRects( screen, numrects, rects);
00454 postScreenUpdate( screen );
00455
00456 if ( *mouseUpdateFlag )
00457 SDL_ShowCursor( 1 );
00458 }
00459
00460
00461 void InitScreenOp::execute()
00462 {
00463 if ( *mouseUpdateFlag )
00464 SDL_ShowCursor( 0 );
00465
00466 SDL_Surface* screen = SDL_SetVideoMode(x, y, depth, flags);
00467 if (screen == NULL)
00468 screen = SDL_SetVideoMode(x, y, depth, flags & ~SDL_FULLSCREEN );
00469
00470 srf( screen );
00471 initASCGraphicSubsystem( screen );
00472
00473 if ( *mouseUpdateFlag )
00474 SDL_ShowCursor( 1 );
00475 };
00476
00477
00478 bool processGraphicsQueue()
00479 {
00480 #ifdef FirstThreadEvents
00481 GraphicsQueueOperation* gqo = NULL;
00482 SDL_mutexP( graphicsQueueMutex );
00483 if ( !graphicsQueue.empty() ) {
00484 gqo = graphicsQueue.front();
00485 SDL_mutexV( graphicsQueueMutex );
00486 if ( gqo ) {
00487 gqo->execute();
00488
00489 SDL_mutexP( graphicsQueueMutex );
00490 graphicsQueue.pop_front();
00491 SDL_mutexV( graphicsQueueMutex );
00492 delete gqo;
00493 return true;
00494 } else
00495 return false;
00496 } else {
00497 SDL_mutexV( graphicsQueueMutex );
00498 return false;
00499 }
00500 #else
00501 return false;
00502 #endif
00503 }
00504
00505 int eventthread ( void* nothing )
00506 {
00507 #ifdef FirstThreadEvents
00508 eventThreadRunning = true;
00509 #endif
00510 while ( !closeEventThread ) {
00511 if ( !processEvents() )
00512 SDL_Delay(10);
00513 processGraphicsQueue();
00514 ticker = getTicker();
00515 }
00516 #ifdef FirstThreadEvents
00517 eventThreadRunning = false;
00518 while ( processGraphicsQueue() )
00519 SDL_Delay(10);
00520 #endif
00521 return closeEventThread;
00522 }
00523
00524
00525 int getTicker()
00526 {
00527 return SDL_GetTicks() / 10;
00528 }
00529
00530 #ifdef FirstThreadEvents
00531 int (*_gamethread)(void *);
00532
00533 int gameThreadWrapper ( void* data )
00534 {
00535 try {
00536 int res = _gamethread ( data );
00537 closeEventThread = 1;
00538 return res;
00539 }
00540 #ifndef WIN32
00541 catch ( ... ) {
00542 fatalError ("An unhandled exception occured. Quitting application");
00543 }
00544 #else
00545 catch ( ASCexception ) {
00546 fatalError ("An unhandled exception occured. Quitting application");
00547 }
00548 #endif
00549 closeEventThread = -1;
00550 return -1;
00551 }
00552 #endif
00553
00554
00556 SDL_Thread* secondThreadHandle = NULL;
00557
00558
00559
00560 int initializeEventHandling ( int (*gamethread)(void *) , void *data )
00561 {
00562
00563 mouseparams.xsize = 10;
00564 mouseparams.ysize = 10;
00565
00566 keyboardmutex = SDL_CreateMutex ();
00567 if ( !keyboardmutex ) {
00568 printf("creating keyboard mutex failed\n" );
00569 exit(1);
00570 }
00571
00572 eventHandlingMutex = SDL_CreateMutex ();
00573 if ( !eventHandlingMutex ) {
00574 printf("creating eventHandling mutex failed\n" );
00575 exit(1);
00576 }
00577
00578
00579 eventQueueMutex = SDL_CreateMutex ();
00580 if ( !eventQueueMutex ) {
00581 printf("creating eventQueueMutex failed\n" );
00582 exit(1);
00583 }
00584
00585 graphicsQueueMutex = SDL_CreateMutex();
00586 if ( !graphicsQueueMutex ) {
00587 printf("creating graphicsQueueMutex failed\n" );
00588 exit(1);
00589 }
00590
00591 SDL_EnableUNICODE ( 1 );
00592 SDL_EnableKeyRepeat ( 250, 30 );
00593
00594
00595 #ifdef FirstThreadEvents
00596 _gamethread = gamethread;
00597 secondThreadHandle = SDL_CreateThread ( gameThreadWrapper, data );
00598 int res = eventthread( NULL );
00599 #else
00600 secondThreadHandle = SDL_CreateThread ( eventthread, NULL );
00601 int res = gamethread( data );
00602 closeEventThread = 1;
00603 #endif
00604
00605
00606 SDL_WaitThread ( secondThreadHandle, NULL );
00607 return res;
00608 }
00609
00610
00611
00612 void exit_asc( int returnresult )
00613 {
00614 #ifndef FirstThreadEvents
00615 if ( secondThreadHandle ) {
00616 closeEventThread = 1;
00617 SDL_WaitThread ( secondThreadHandle, NULL );
00618 }
00619 exit( returnresult );
00620 #else
00621 if ( secondThreadHandle ) {
00622 throw ThreadExitException();
00623 }
00624 exit( returnresult );
00625
00626
00627 #endif
00628
00629
00630 }
00631
00632
00633 bool setEventRouting( bool queue, bool legacy )
00634 {
00635 bool prev = _queueEvents;
00636
00637 _fillLegacyEventStructures = legacy;
00638
00639 _queueEvents = queue;
00640 if ( !queue ) {
00641
00642 SDL_mutexP( eventQueueMutex );
00643 while ( !eventQueue.empty())
00644 eventQueue.pop();
00645 SDL_mutexV( eventQueueMutex );
00646 }
00647
00648 return prev;
00649 }
00650
00651 bool legacyEventSystemActive()
00652 {
00653 return _fillLegacyEventStructures;
00654 }
00655
00656
00657 bool getQueuedEvent ( SDL_Event& event )
00658 {
00659 SDL_mutexP( eventQueueMutex );
00660 if ( !eventQueue.empty() ) {
00661 event = eventQueue.front();
00662 eventQueue.pop();
00663 SDL_mutexV( eventQueueMutex );
00664 return true;
00665 }
00666 SDL_mutexV( eventQueueMutex );
00667 return false;
00668 }
00669
00670 bool peekEvent ( SDL_Event& event )
00671 {
00672 SDL_mutexP( eventQueueMutex );
00673 if ( !eventQueue.empty() ) {
00674 event = eventQueue.front();
00675 SDL_mutexV( eventQueueMutex );
00676 return true;
00677 }
00678 SDL_mutexV( eventQueueMutex );
00679 return false;
00680 }
00681
00682