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 "../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
00158 tkey r_key(void)
00159 {
00160 int found = 0;
00161 tkey key;
00162 do {
00163 int r = SDL_mutexP ( keyboardmutex );
00164 if ( !r ) {
00165 if ( !keybuffer_sym.empty() ) {
00166 key = keybuffer_sym.front();
00167 keybuffer_sym.pop();
00168 keybuffer_prnt.pop();
00169 found++;
00170 }
00171 r = SDL_mutexV ( keyboardmutex );
00172 }
00173 if (!found ) {
00174 int t = ticker;
00175 while ( t + 5 > ticker )
00176 releasetimeslice();
00177 }
00178 } while ( !found );
00179 return key;
00180 }
00181
00182 int rp_key(void)
00183 {
00184 int found = 0;
00185 tkey key;
00186 do {
00187 int r = SDL_mutexP ( keyboardmutex );
00188 if ( !r ) {
00189 if ( !keybuffer_prnt.empty() ) {
00190 key = keybuffer_prnt.front();
00191 keybuffer_sym.pop();
00192 keybuffer_prnt.pop();
00193 found++;
00194 }
00195 r = SDL_mutexV ( keyboardmutex );
00196 }
00197 if (!found ) {
00198 int t = ticker;
00199 while ( t + 5 > ticker )
00200 releasetimeslice();
00201 }
00202 } while ( !found );
00203 return key;
00204 }
00205
00206 void getkeysyms ( tkey* keysym, int* keyprnt )
00207 {
00208 int found = 0;
00209 do {
00210 int r = SDL_mutexP ( keyboardmutex );
00211 if ( !r ) {
00212 if ( !keybuffer_prnt.empty() ) {
00213 *keysym = keybuffer_sym.front();
00214 *keyprnt = keybuffer_prnt.front();
00215 keybuffer_sym.pop();
00216 keybuffer_prnt.pop();
00217 found++;
00218 }
00219 r = SDL_mutexV ( keyboardmutex );
00220 }
00221 if (!found ) {
00222 int t = ticker;
00223 while ( t + 5 > ticker )
00224 releasetimeslice();
00225 }
00226 } while ( !found );
00227 }
00228
00229
00230 char skeypress(tkey keynr)
00231 {
00232 Uint8 *keystate = SDL_GetKeyState ( NULL );
00233 return keystate[ keynr ];
00234 }
00235
00236
00237
00238
00239 void wait(void)
00240 {}
00241
00242
00243
00244 tkey char2key(int c )
00245 {
00246 if ( c < 128 )
00247 return tolower(c);
00248 else
00249 return ct_invvalue;
00250 }
00251
00252
00253 int releasetimeslice( void )
00254 {
00255 SDL_Delay(10);
00256 if ( redrawScreen ) {
00257 redrawScreen = false;
00258 copy2screen();
00259 }
00260 return 0;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 volatile int ticker = 0;
00279
00280 void ndelay(int time)
00281 {
00282 long l;
00283
00284 l = ticker;
00285 do {
00286 releasetimeslice();
00287 } while (ticker - l > time);
00288 }
00289
00290
00291 int tticker = 0;
00292
00293 void starttimer(void)
00294 {
00295 tticker = ticker;
00296 }
00297
00298 char time_elapsed(int time)
00299 {
00300 if (tticker + time <= ticker) return 1;
00301 else return 0;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 #include <iostream>
00313
00314 volatile int closeEventThread = 0;
00315
00316 const int keyTranslationNum = 7;
00317 int keyTranslation[keyTranslationNum][2] = { { 228, 132 },
00318 { 246, 148 },
00319 { 252, 129 },
00320 { 196, 142 },
00321 { 214, 153 },
00322 { 220, 154 },
00323 { 223, 225 } };
00324
00325 int processEvents ( )
00326 {
00327 SDL_mutexP ( eventHandlingMutex );
00328
00329 SDL_Event event;
00330 int result;
00331 if ( SDL_PollEvent ( &event ) == 1) {
00332 if ( _fillLegacyEventStructures ) {
00333 switch ( event.type ) {
00334 case SDL_MOUSEBUTTONUP:
00335 case SDL_MOUSEBUTTONDOWN:
00336 {
00337 int taste = mouseTranslate(event.button.button - 1);
00338 int state = event.button.type == SDL_MOUSEBUTTONDOWN;
00339 if ( state )
00340 mouseparams.taste |= (1 << taste);
00341 else
00342 mouseparams.taste &= ~(1 << taste);
00343 mouseparams.x = event.button.x;
00344 mouseparams.y = event.button.y;
00345 }
00346 break;
00347
00348 case SDL_MOUSEMOTION:
00349 {
00350 mouseparams.x = event.motion.x;
00351 mouseparams.y = event.motion.y;
00352 mouseparams.x1 = event.motion.x;
00353 mouseparams.y1 = event.motion.y;
00354 mouseparams.taste = 0;
00355 for ( int i = 0; i < 3; i++ )
00356 if ( event.motion.state & (1 << i) )
00357 mouseparams.taste |= 1 << mouseTranslate(i);
00358 }
00359 break;
00360 case SDL_KEYDOWN:
00361 {
00362 int r = SDL_mutexP ( keyboardmutex );
00363 if ( !r ) {
00364 tkey key = event.key.keysym.sym;
00365 if ( event.key.keysym.mod & KMOD_ALT )
00366 key |= ct_altp;
00367 if ( event.key.keysym.mod & KMOD_CTRL )
00368 key |= ct_stp;
00369 if ( event.key.keysym.mod & KMOD_SHIFT )
00370 key |= ct_shp;
00371 keybuffer_sym.push ( key );
00372
00373 int newsym = event.key.keysym.unicode;
00374 for ( int i = 0; i < keyTranslationNum; i++ )
00375 if ( event.key.keysym.unicode == keyTranslation[i][0] )
00376 newsym = keyTranslation[i][1];
00377 keybuffer_prnt.push ( newsym );
00378 r = SDL_mutexV ( keyboardmutex );
00379 }
00380 }
00381 break;
00382 case SDL_KEYUP:
00383 {}
00384 break;
00385
00386 case SDL_QUIT:
00387 exitprogram = 1;
00388 break;
00389 #ifdef _WIN32_
00390 case SDL_ACTIVEEVENT:
00391 redrawScreen = true;
00392 break;
00393 #endif
00394 }
00395 } else {
00396 #ifdef _WIN32_
00397 if ( event.type == SDL_ACTIVEEVENT ) {
00398 queueOperation( new UpdateRectOp( SDL_GetVideoSurface(), 0,0,0,0), false, true );
00399 }
00400 #endif
00401
00402 }
00403 result = 1;
00404 if ( _queueEvents ) {
00405 SDL_mutexP( eventQueueMutex );
00406 eventQueue.push ( event );
00407 SDL_mutexV( eventQueueMutex );
00408 }
00409
00410
00411 } else
00412 result = 0;
00413
00414 SDL_mutexV( eventHandlingMutex );
00415 return result;
00416 }
00417
00418 #if defined(_WIN32_) || defined(__APPLE__)
00419 #define FirstThreadEvents 1
00420 #endif
00421
00422 bool syncGraphics = true;
00423
00424
00425 SigC::Signal1<void,const SDL_Surface*> postScreenUpdate;
00426
00427 void queueOperation( GraphicsQueueOperation* gqo, bool wait, bool forceAsync )
00428 {
00429 if ( !eventThreadRunning ) {
00430 gqo->execute();
00431 delete gqo;
00432 return;
00433 }
00434
00435 SDL_mutexP( graphicsQueueMutex );
00436 graphicsQueue.push_back( gqo );
00437 SDL_mutexV( graphicsQueueMutex );
00438
00439 if ( forceAsync )
00440 return;
00441
00442 if ( syncGraphics || wait ) {
00443 bool finished = false;
00444 do {
00445 SDL_Delay(10);
00446 SDL_mutexP( graphicsQueueMutex );
00447 finished = graphicsQueue.empty();
00448 SDL_mutexV( graphicsQueueMutex );
00449 } while (!finished);
00450 }
00451 }
00452
00453
00454 void UpdateRectOp::execute()
00455 {
00456 if ( *mouseUpdateFlag )
00457 SDL_ShowCursor( 0 );
00458
00459 SDL_UpdateRect( screen, x,y,w,h);
00460 postScreenUpdate( screen );
00461
00462 if ( *mouseUpdateFlag )
00463 SDL_ShowCursor( 1 );
00464 };
00465
00466
00467 UpdateRectsOp::UpdateRectsOp( SDL_Surface *screen, int numrects, SDL_Rect *rects)
00468 {
00469 this->numrects = numrects;
00470 this->rects = new SDL_Rect[numrects];
00471 for ( int i = 0; i< numrects; ++i )
00472 this->rects[i] = rects[i];
00473 this->screen = screen;
00474 };
00475
00476 UpdateRectsOp::~UpdateRectsOp()
00477 {
00478 delete[] rects;
00479 }
00480
00481 void UpdateRectsOp::execute()
00482 {
00483 if ( *mouseUpdateFlag )
00484 SDL_ShowCursor( 0 );
00485
00486 SDL_UpdateRects( screen, numrects, rects);
00487 postScreenUpdate( screen );
00488
00489 if ( *mouseUpdateFlag )
00490 SDL_ShowCursor( 1 );
00491 }
00492
00493
00494 void InitScreenOp::execute()
00495 {
00496 if ( *mouseUpdateFlag )
00497 SDL_ShowCursor( 0 );
00498
00499 SDL_Surface* screen = SDL_SetVideoMode(x, y, depth, flags);
00500 if (screen == NULL)
00501 screen = SDL_SetVideoMode(x, y, depth, flags & ~SDL_FULLSCREEN );
00502
00503 srf( screen );
00504 initASCGraphicSubsystem( screen );
00505
00506 if ( *mouseUpdateFlag )
00507 SDL_ShowCursor( 1 );
00508 };
00509
00510
00511 bool processGraphicsQueue()
00512 {
00513 #ifdef FirstThreadEvents
00514 GraphicsQueueOperation* gqo = NULL;
00515 SDL_mutexP( graphicsQueueMutex );
00516 if ( !graphicsQueue.empty() ) {
00517 gqo = graphicsQueue.front();
00518 SDL_mutexV( graphicsQueueMutex );
00519 if ( gqo ) {
00520 gqo->execute();
00521
00522 SDL_mutexP( graphicsQueueMutex );
00523 graphicsQueue.pop_front();
00524 SDL_mutexV( graphicsQueueMutex );
00525 delete gqo;
00526 return true;
00527 } else
00528 return false;
00529 } else {
00530 SDL_mutexV( graphicsQueueMutex );
00531 return false;
00532 }
00533 #else
00534 return false;
00535 #endif
00536 }
00537
00538 int eventthread ( void* nothing )
00539 {
00540 #ifdef FirstThreadEvents
00541 eventThreadRunning = true;
00542 #endif
00543 while ( !closeEventThread ) {
00544 if ( !processEvents() )
00545 SDL_Delay(10);
00546 processGraphicsQueue();
00547 ticker = getTicker();
00548 }
00549 #ifdef FirstThreadEvents
00550 eventThreadRunning = false;
00551 while ( processGraphicsQueue() )
00552 SDL_Delay(10);
00553 #endif
00554 return closeEventThread;
00555 }
00556
00557
00558 int getTicker()
00559 {
00560 return SDL_GetTicks() / 10;
00561 }
00562
00563 #ifdef FirstThreadEvents
00564 int (*_gamethread)(void *);
00565
00566 int gameThreadWrapper ( void* data )
00567 {
00568 try {
00569 int res = _gamethread ( data );
00570 closeEventThread = 1;
00571 return res;
00572 }
00573 #ifndef WIN32
00574 catch ( ... ) {
00575 fatalError ("An unhandled exception occured. Quitting application");
00576 }
00577 #else
00578 catch ( ASCexception ) {
00579 fatalError ("An unhandled exception occured. Quitting application");
00580 }
00581 #endif
00582 closeEventThread = -1;
00583 return -1;
00584 }
00585 #endif
00586
00587
00589 SDL_Thread* secondThreadHandle = NULL;
00590
00591
00592
00593 int initializeEventHandling ( int (*gamethread)(void *) , void *data )
00594 {
00595
00596 mouseparams.xsize = 10;
00597 mouseparams.ysize = 10;
00598
00599 keyboardmutex = SDL_CreateMutex ();
00600 if ( !keyboardmutex ) {
00601 printf("creating keyboard mutex failed\n" );
00602 exit(1);
00603 }
00604
00605 eventHandlingMutex = SDL_CreateMutex ();
00606 if ( !eventHandlingMutex ) {
00607 printf("creating eventHandling mutex failed\n" );
00608 exit(1);
00609 }
00610
00611
00612 eventQueueMutex = SDL_CreateMutex ();
00613 if ( !eventQueueMutex ) {
00614 printf("creating eventQueueMutex failed\n" );
00615 exit(1);
00616 }
00617
00618 graphicsQueueMutex = SDL_CreateMutex();
00619 if ( !graphicsQueueMutex ) {
00620 printf("creating graphicsQueueMutex failed\n" );
00621 exit(1);
00622 }
00623
00624 SDL_EnableUNICODE ( 1 );
00625 SDL_EnableKeyRepeat ( 250, 30 );
00626
00627
00628 #ifdef FirstThreadEvents
00629 _gamethread = gamethread;
00630 secondThreadHandle = SDL_CreateThread ( gameThreadWrapper, data );
00631 int res = eventthread( NULL );
00632 #else
00633 secondThreadHandle = SDL_CreateThread ( eventthread, NULL );
00634 int res = gamethread( data );
00635 closeEventThread = 1;
00636 #endif
00637
00638
00639 SDL_WaitThread ( secondThreadHandle, NULL );
00640 return res;
00641 }
00642
00643
00644
00645 void exit_asc( int returnresult )
00646 {
00647 #ifndef FirstThreadEvents
00648 if ( secondThreadHandle ) {
00649 closeEventThread = 1;
00650 SDL_WaitThread ( secondThreadHandle, NULL );
00651 }
00652 exit( returnresult );
00653 #else
00654 if ( secondThreadHandle ) {
00655 throw ThreadExitException();
00656 }
00657 exit( returnresult );
00658
00659
00660 #endif
00661
00662
00663 }
00664
00665
00666 bool setEventRouting( bool queue, bool legacy )
00667 {
00668 bool prev = _queueEvents;
00669
00670 _fillLegacyEventStructures = legacy;
00671
00672 _queueEvents = queue;
00673 if ( !queue ) {
00674
00675 SDL_mutexP( eventQueueMutex );
00676 while ( !eventQueue.empty())
00677 eventQueue.pop();
00678 SDL_mutexV( eventQueueMutex );
00679 }
00680
00681 return prev;
00682 }
00683
00684 bool legacyEventSystemActive()
00685 {
00686 return _fillLegacyEventStructures;
00687 }
00688
00689
00690 bool getQueuedEvent ( SDL_Event& event )
00691 {
00692 SDL_mutexP( eventQueueMutex );
00693 if ( !eventQueue.empty() ) {
00694 event = eventQueue.front();
00695 eventQueue.pop();
00696 SDL_mutexV( eventQueueMutex );
00697 return true;
00698 }
00699 SDL_mutexV( eventQueueMutex );
00700 return false;
00701 }
00702
00703 bool peekEvent ( SDL_Event& event )
00704 {
00705 SDL_mutexP( eventQueueMutex );
00706 if ( !eventQueue.empty() ) {
00707 event = eventQueue.front();
00708 SDL_mutexV( eventQueueMutex );
00709 return true;
00710 }
00711 SDL_mutexV( eventQueueMutex );
00712 return false;
00713 }
00714
00715